-
Notifications
You must be signed in to change notification settings - Fork 3
✨refactor: remove userID, add external secure hasher to Auth API call #2293
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -12,6 +12,7 @@ import ( | |||||||||||||||||||||||||||||||||||||||||
| "net/http" | ||||||||||||||||||||||||||||||||||||||||||
| "net/url" | ||||||||||||||||||||||||||||||||||||||||||
| "os" | ||||||||||||||||||||||||||||||||||||||||||
| "os/exec" | ||||||||||||||||||||||||||||||||||||||||||
| "strings" | ||||||||||||||||||||||||||||||||||||||||||
| "time" | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -507,8 +508,36 @@ func APICall(reqURL string, request proto.Message) []byte { | |||||||||||||||||||||||||||||||||||||||||
| return decodedAuthBuf.Message | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| func getSecureHash(data []byte) (string, error) { | ||||||||||||||||||||||||||||||||||||||||||
| binaryPath := "./secure_hasher" | ||||||||||||||||||||||||||||||||||||||||||
| info, err := os.Stat(binaryPath) | ||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||
| if os.IsNotExist(err) { | ||||||||||||||||||||||||||||||||||||||||||
| return "", fmt.Errorf("secure hasher binary not found at %s", binaryPath) | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
| return "", fmt.Errorf("failed to stat secure hasher binary: %w", err) | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
| if info.IsDir() { | ||||||||||||||||||||||||||||||||||||||||||
| return "", fmt.Errorf("secure hasher path is a directory: %s", binaryPath) | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| cmd := exec.Command(binaryPath) | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| // Pipe the raw bytes into the binary's stdin | ||||||||||||||||||||||||||||||||||||||||||
| cmd.Stdin = bytes.NewReader(data) | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| var out bytes.Buffer | ||||||||||||||||||||||||||||||||||||||||||
| cmd.Stdout = &out | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| if err := cmd.Run(); err != nil { | ||||||||||||||||||||||||||||||||||||||||||
| return "", fmt.Errorf("failed to execute hasher: %w", err) | ||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+532
to
+533
|
||||||||||||||||||||||||||||||||||||||||||
| if err := cmd.Run(); err != nil { | |
| return "", fmt.Errorf("failed to execute hasher: %w", err) | |
| var errBuf bytes.Buffer | |
| cmd.Stderr = &errBuf | |
| if err := cmd.Run(); err != nil { | |
| return "", fmt.Errorf("failed to execute hasher: %w; stderr: %s", err, errBuf.String()) |
Copilot
AI
Mar 30, 2026
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.
exec.Command(binaryPath) is run without any timeout/cancellation. If the external hasher hangs (or blocks on stdin), APIAuthenticatedCall will hang the request path. Use exec.CommandContext with a reasonable timeout (e.g., a few seconds) so the API call can fail fast and the bot remains responsive.
Copilot
AI
Mar 30, 2026
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.
getSecureHash returns whatever the external process writes to stdout after trimming whitespace, but APIAuthenticatedCall assumes it's a valid auth code. Add basic validation (e.g., non-empty, expected hex length/charset) and return an error if the output is malformed to avoid sending bad auth requests upstream.
| return strings.TrimSpace(out.String()), nil | |
| hash := strings.TrimSpace(out.String()) | |
| if hash == "" { | |
| return "", fmt.Errorf("secure hasher returned empty output") | |
| } | |
| // Validate that the output looks like a hex-encoded hash (e.g., SHA-256). | |
| for i := 0; i < len(hash); i++ { | |
| c := hash[i] | |
| if !((c >= '0' && c <= '9') || | |
| (c >= 'a' && c <= 'f') || | |
| (c >= 'A' && c <= 'F')) { | |
| return "", fmt.Errorf("secure hasher returned non-hex character %q", c) | |
| } | |
| } | |
| // Enforce an expected hash length (64 characters is typical for SHA-256). | |
| if len(hash) != 64 { | |
| return "", fmt.Errorf("secure hasher returned unexpected length %d", len(hash)) | |
| } | |
| return hash, nil |
Copilot
AI
Mar 30, 2026
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 change alters the request envelope semantics: AuthenticatedMessage.Message used to contain base64-encoded innerBin and UserId was populated; now the raw protobuf bytes are sent and user_id is omitted in favor of code. Because this is an external API contract, please ensure the server expects raw message bytes (not base64 text) and does not require user_id; otherwise these calls will fail at runtime. If both formats must be supported, consider keeping backward-compatible fields or gating behavior by endpoint/version.
Copilot
AI
Mar 30, 2026
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.
APIAuthenticatedCall now depends on executing an external binary (secure_hasher), but there are no tests covering the request-envelope creation (hash generation + AuthenticatedMessage fields). Since there are existing tests in this package, consider adding a unit test that verifies APIAuthenticatedCall builds the correct AuthenticatedMessage (ideally by injecting/mocking the hash function so tests don't shell out).
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.
getSecureHashhard-codes a relative path (./secure_hasher). This is brittle in production (depends on current working directory) and makes deployments harder to reason about. Consider making the hasher path configurable (config/env/flag) and/or resolving it to an absolute path once at startup, rather than re-stat'ing a relative path on every call.