-
Notifications
You must be signed in to change notification settings - Fork 1
feat: add signature agent #71
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A couple edge cases in the new signature-agent/JWK wiring that might bite users:
-
pkg/extensions/webbotauth.go:injectJWKIntoBackgroundTs()interpolatesjwkDatastraight into TS (fmt.Sprintf("const jwk = %s;", jwkData)). Since--keyaccepts PEM or JWK, this will generate invalid TS for PEM inputs (and also makes it easy to inject arbitrary code if the file isn’t strict JSON). It seems worth validating/normalizing as JSON before writing, and ensuring the injected value is always a JWK.// before building, ensure we have a JWK string to inject jwkData := keyData if util.IsPEMKey(keyData) { return "", fmt.Errorf("--key is PEM, but background.ts injection expects JWK") } // in injectJWKIntoBackgroundTs var jwk any if err := json.Unmarshal([]byte(jwkData), &jwk); err != nil { return fmt.Errorf("invalid JWK JSON: %w", err) } normalized, _ := json.Marshal(jwk) replacement := fmt.Sprintf("const jwk = %s;", normalized) -
pkg/extensions/webbotauth.go:SIGNATURE_AGENT_URLis set even when the flag is empty (SIGNATURE_AGENT_URL=). If the JS build has its own defaulting logic based on “env var present”, this can change behavior unexpectedly. Consider only appending the env var when non-empty.env := os.Environ() if strings.TrimSpace(signatureAgentURL) != "" { env = append(env, "SIGNATURE_AGENT_URL="+strings.TrimSpace(signatureAgentURL)) } npmBuild.Env = env -
pkg/extensions/webbotauth.go:webBotAuthDownloadURLnow trackskernel/web-bot-authmain.zip. That’s convenient, but it also makes builds non-reproducible and can break CLI builds whenmainchanges. If stability matters, pinning to a tag/commit (or making the source configurable) would help. -
cmd/extensions.go: minor UX: if--signature-agentneeds to be a URL, a quickurl.ParseRequestURIvalidation (when non-empty) could catch typos early.
| return "", fmt.Errorf("failed to validate PEM key: %w", err) | ||
| } | ||
|
|
||
| jwkData, err = util.ConvertPEMToJWK(keyData) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could just support JWK keys lol so we wouldn't need converting pack and forth
| if err != nil { | ||
| return "", fmt.Errorf("failed to convert JWK to PEM: %w", err) | ||
| } | ||
| jwkData = keyData |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Raw JWK input injected without re-serialization
Low Severity
When a user provides a JWK file, jwkData = keyData uses the raw file contents directly for JavaScript injection, while ConvertJWKToPEM only validates the JSON structure. Go's json.Unmarshal ignores trailing data after valid JSON, so a malicious JWK file containing {"kty":"OKP"...}; malicious_code(); would pass validation but inject the trailing code into background.ts. The PEM path safely uses re-serialized JSON from ConvertPEMToJWK, but the JWK path lacks this sanitization.
| extensionsBuildWebBotAuthCmd.Flags().String("url", "http://127.0.0.1:10001", "Base URL for update.xml and policy templates") | ||
| extensionsBuildWebBotAuthCmd.Flags().String("key", "", "Path to Ed25519 private key file (JWK or PEM format)") | ||
| extensionsBuildWebBotAuthCmd.Flags().String("upload", "", "Upload extension to Kernel with specified name (e.g., --upload web-bot-auth)") | ||
| extensionsBuildWebBotAuthCmd.Flags().String("signature-agent", "", "URL of the signature agent") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: the description is vague. consider something like: "Base URL of the signature agent (e.g., https://agent.example.com). Verifiers will look up /.well-known/http-message-signatures-directory at this URL."
rgarcia
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good! Solid implementation of the PEM↔JWK conversion and signature agent support.
One minor nit on the flag description.
| keyPath, _ := cmd.Flags().GetString("key") | ||
| uploadName, _ := cmd.Flags().GetString("upload") | ||
|
|
||
| signatureAgentURL, _ := cmd.Flags().GetString("signature-agent") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
perhaps we should add that kernel is explicitly add to the helper that Kernel is expecting a ed25519 key. This reason being that ConvertPEMToJWK validates that
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is mentioned in the --key flag
extensionsBuildWebBotAuthCmd.Flags().String("key", "", "Path to Ed25519 private key file (JWK or PEM format)")
| // Replace the import line with an inline constant | ||
| // Find: import jwk from "../../rfc9421-keys/ed25519.json" assert { type: "json" }; | ||
| // Replace with: const jwk = {your-jwk-here}; | ||
| searchPattern := `import jwk from "../../rfc9421-keys/ed25519.json" assert { type: "json" };` | ||
| replacement := fmt.Sprintf("const jwk = %s;", jwkData) | ||
|
|
||
| if !strings.Contains(contentStr, searchPattern) { | ||
| return fmt.Errorf("could not find JWK import statement in background.ts") | ||
| } | ||
|
|
||
| contentStr = strings.Replace(contentStr, searchPattern, replacement, 1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This part seems kinda flakey. We are basically writing typescript code from Go to make a one line replacement.
Perhaps in later edits to https://github.com/kernel/web-bot-auth, we can maybe templatizes this file so that using https://pkg.go.dev/text/template in go we can easily replace the jwkData
| // ConvertPEMToJWK converts an Ed25519 PEM private key to JWK format | ||
| func ConvertPEMToJWK(pemData string) (string, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i wish there was easy util to make this, but it seems no. So looks good to me
| // ConvertPEMToJWK converts an Ed25519 PEM private key to JWK format | ||
| func ConvertPEMToJWK(pemData string) (string, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we wanna rename it so that it is explicit that it only converts Ed25519 PEM to JWK format
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me. Some minor comments. I tested it end to end. It seems good to 🚢
- Compile this
- Create an extension for Kernel
- Upload that extension to a locally running docker
- Go to https://crawltest.com/cdn-cgi/web-bot-auth on that browser
- Inspect the HTTP headers that are injected on the request.
- Observe that
Signature-Agentis as specified - Observe that keyid matches the published https://www.kernel.sh/.well-known/http-message-signatures-directory
Note
Introduces signature-agent support and key handling improvements for building the Cloudflare web-bot-auth extension.
--signature-agentflag toextensions build-web-bot-authincmd/extensions.go; passes through toextensions.BuildWebBotAuthand exportsSIGNATURE_AGENT_URLduringnpm run build:chromeandbundle:chrome.util.ConvertPEMToJWK/ConvertJWKToPEM), writesprivate_key.pem, and replaces the background key import with an inlinejwkviainjectJWKIntoBackgroundTs.pkg/extensions/webbotauth.go).ConvertPEMToJWKinpkg/util/crypto.gowith comprehensive tests, including roundtrip PEM↔JWK inpkg/util/crypto_test.go.Written by Cursor Bugbot for commit 69437a1. This will update automatically on new commits. Configure here.