feat(core, worker): update worker signature#257
Conversation
Summary of ChangesHello @mizhm, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request implements a new security layer for worker connections by introducing a mandatory signature validation process. Workers now provide a signature when joining the system, which the core API verifies against a predefined value. This ensures that only authorized workers can connect, significantly improving the overall security posture of the worker infrastructure. The changes involve updates to API contracts, core service logic, and the worker client to support this new authentication mechanism. Highlights
🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console. Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Pull request overview
Updates the worker “join” contract to include a signature and wires it through the worker client and core API join handling.
Changes:
- Add optional
signatureto worker join DTOs (core API + generated clients). - Pass
WORKER_SIGNATUREfrom the worker when calling/workers/join. - Enforce worker signature checking in
WorkersService.join.
Reviewed changes
Copilot reviewed 6 out of 8 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
worker/tool/tool.ts |
Sends signature on join and reformats strings/headers. |
worker/services/core-api/api.ts |
Updates generated WorkerJoinDto type to include signature?: string. |
worker/bun.lock |
Lockfile metadata update (configVersion). |
package-lock.json |
Large lockfile metadata changes (adds/removes peer flags). |
core-api/src/modules/workers/workers.service.ts |
Enforces signature validation during join. |
core-api/src/modules/workers/workers.controller.ts |
Attempts to plumb signature into gRPC join path. |
core-api/src/modules/workers/dto/workers.dto.ts |
Adds signature?: string to REST join DTO. |
console/src/services/apis/gen/queries.ts |
Updates generated WorkerJoinDto type to include signature?: string. |
Comments suppressed due to low confidence (1)
worker/tool/tool.ts:142
connectToCore()treats any 401 from/workers/joinas an "API key is invalid" case, but with the newsignatureparameter a 401 may also mean an invalid/missing signature. Also, despite the comment saying "don't retry", the loop continues retrying forever after logging. Consider distinguishing auth failures (API key vs signature) using the server error message/status and aborting (throw/return) on 401 to avoid an infinite retry loop.
const worker: any = await coreApi.workersControllerJoin({
apiKey: process.env.API_KEY! || process.env.OASM_CLOUD_APIKEY!,
signature: process.env.WORKER_SIGNATURE,
});
Tool.workerId = worker.id;
Tool.token = worker.token;
logger.success(
`CONNECTED ✅ WorkerId: ${Tool.workerId?.split("-")[0]}`,
);
// Wait until Tool.workerId is set (by SSE handler)
await this.waitUntil(() => !!Tool.workerId, 1000);
return; // success, exit the method
} catch (e: any) {
// If we get a 401 error, don't retry - just throw an API key invalid error
if (e?.response?.status === 401) {
logger.error("API key is invalid. Cannot connect to core.");
}
attempt++;
logger.error(
`Cannot connect to core ${process.env.API} (attempt ${attempt}):`,
);
await this.sleep(1000 * attempt); // exponential backoff delay
}
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Code Review
The pull request introduces a new signature field for worker joining, enhancing security by allowing workers to authenticate with a shared secret. The changes span across type definitions, DTOs, the worker controller, and the worker service to implement this new authentication mechanism. There are a couple of high-severity issues related to type consistency and handling of the optional signature field that need to be addressed.
| @GrpcMethod('WorkersService', 'Join') | ||
| async grpcJoin(requests: { | ||
| apiKey: string; | ||
| signature: string; |
There was a problem hiding this comment.
The grpcJoin method's requests parameter type explicitly defines signature: string;, implying it's a required field. However, the WorkerJoinDto (defined in workers.dto.ts and used in the workersService.join method) marks signature as optional (signature?: string;). This type mismatch can lead to unexpected behavior or runtime errors if a gRPC client does not provide the signature field, as the service layer might still expect it based on the controller's type definition.
| signature: string; | |
| signature?: string; |
| if (signature !== workerSignature) { | ||
| throw new UnauthorizedException('Invalid worker signature'); |
There was a problem hiding this comment.
The WorkerJoinDto defines signature as an optional field (signature?: string). However, the current logic if (signature !== workerSignature) will throw an UnauthorizedException if signature is undefined (which is allowed by the DTO) and workerSignature is a defined string. This means an optional field effectively becomes required, contradicting the DTO's definition. The check should only be performed if a signature is actually provided in the DTO, or workerSignature should also be undefined if no signature is expected.
| if (signature !== workerSignature) { | |
| throw new UnauthorizedException('Invalid worker signature'); | |
| if (signature && signature !== workerSignature) { |
l1ttps
left a comment
There was a problem hiding this comment.
Hey @mizhm, thanks for working on this security enhancement!
The PR looks good overall and adds an important security layer by implementing worker signature validation. The approach of requiring a signature from workers and validating it against a configured WORKER_SIGNATURE environment variable is solid.
However, I noticed a potential security concern that needs to be addressed:
- The signature field is marked as optional (
signature?: string) in some DTOs but the validation logic treats it as required - The code uses
|| ''which could allow empty signatures to pass validation if the WORKER_SIGNATURE environment variable is not set - The example.env files don't include the new WORKER_SIGNATURE variable that workers will need
Could you please address these points:
- Make the signature field consistently required in the DTO validation when it's expected
- Ensure proper handling when WORKER_SIGNATURE is not configured (perhaps fail securely rather than allowing empty signatures)
- Update the example.env files to include the WORKER_SIGNATURE variable with appropriate documentation
This security feature is important, so let's make sure it's implemented robustly. Please make these changes and we can merge this.
No description provided.