Skip to content

Commit 6789809

Browse files
committed
fix(samples/go): resolve Super-Linter issues in signing and verifying sample
1 parent 66fed00 commit 6789809

5 files changed

Lines changed: 54 additions & 30 deletions

File tree

samples/go/agents/signing_and_verifying/Containerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ COPY . .
99

1010
RUN CGO_ENABLED=0 GOOS=linux go build -o agent .
1111

12-
FROM alpine:latest
12+
FROM alpine:3.21
1313

1414
WORKDIR /app
1515

samples/go/agents/signing_and_verifying/README.md

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,19 @@ python3 __main__.py --agent http://localhost:9999
5757

5858
## Disclaimer
5959

60-
Important: The sample code provided is for demonstration purposes and illustrates the mechanics of the Agent-to-Agent (A2A) protocol. When building production applications, it is critical to treat any agent operating outside of your direct control as a potentially untrusted entity.
61-
62-
All data received from an external agent—including but not limited to its AgentCard, messages, artifacts, and task statuses—should be handled as untrusted input. For example, a malicious agent could provide an AgentCard containing crafted data in its fields (e.g., description, name, skills.description). If this data is used without sanitization to construct prompts for a Large Language Model (LLM), it could expose your application to prompt injection attacks. Failure to properly validate and sanitize this data before use can introduce security vulnerabilities into your application.
63-
64-
Developers are responsible for implementing appropriate security measures, such as input validation and secure handling of credentials to protect their systems and users.
60+
Important: The sample code provided is for demonstration purposes
61+
and illustrates the mechanics of the Agent-to-Agent (A2A) protocol.
62+
When building production applications, it is critical to treat any agent
63+
operating outside of your direct control as a potentially untrusted entity.
64+
65+
All data received from an external agent—including but not limited to its AgentCard,
66+
messages, artifacts, and task statuses—should be handled as untrusted input.
67+
For example, a malicious agent could provide an AgentCard containing crafted data
68+
in its fields (e.g., description, name, skills.description). If this data is used
69+
without sanitization to construct prompts for a Large Language Model (LLM),
70+
it could expose your application to prompt injection attacks. Failure to properly
71+
validate and sanitize this data before use can introduce security vulnerabilities
72+
into your application.
73+
74+
Developers are responsible for implementing appropriate security measures,
75+
such as input validation and secure handling of credentials to protect their systems and users.

samples/go/agents/signing_and_verifying/main.go

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@ import (
1717
"github.com/a2aproject/a2a-go/a2asrv"
1818
)
1919

20+
const (
21+
modeText = "text"
22+
serverURL = "http://localhost:9999"
23+
es256Alg = "ES256"
24+
)
25+
2026
func main() {
2127
runClientFlag := flag.Bool("client", false, "Run the test client instead of starting server only")
2228
flag.Parse()
@@ -44,7 +50,7 @@ func main() {
4450
if err != nil {
4551
log.Fatalf("Failed to marshal keys JSON: %v", err)
4652
}
47-
if err := os.WriteFile("public_keys.json", keysJSON, 0644); err != nil {
53+
if err := os.WriteFile("public_keys.json", keysJSON, 0600); err != nil {
4854
log.Fatalf("Failed to save public_keys.json: %v", err)
4955
}
5056

@@ -67,16 +73,16 @@ func main() {
6773
publicAgentCard := &a2a.AgentCard{
6874
Name: "Signed Agent",
6975
Description: "An Agent that is signed",
70-
IconURL: "http://localhost:9999/",
76+
IconURL: serverURL + "/",
7177
Version: "1.0.0",
72-
DefaultInputModes: []string{"text"},
73-
DefaultOutputModes: []string{"text"},
78+
DefaultInputModes: []string{modeText},
79+
DefaultOutputModes: []string{modeText},
7480
Capabilities: a2a.AgentCapabilities{Streaming: true, ExtendedAgentCard: true},
7581
SupportedInterfaces: []*a2a.AgentInterface{
7682
{
7783
ProtocolBinding: a2a.TransportProtocolJSONRPC,
7884
ProtocolVersion: a2a.Version,
79-
URL: "http://localhost:9999",
85+
URL: serverURL,
8086
},
8187
},
8288
Skills: []a2a.AgentSkill{skill},
@@ -85,16 +91,16 @@ func main() {
8591
extendedAgentCard := &a2a.AgentCard{
8692
Name: "Signed Agent - Extended Edition",
8793
Description: "The full-featured signed agent for authenticated users.",
88-
IconURL: "http://localhost:9999/",
94+
IconURL: serverURL + "/",
8995
Version: "1.0.1",
90-
DefaultInputModes: []string{"text"},
91-
DefaultOutputModes: []string{"text"},
96+
DefaultInputModes: []string{modeText},
97+
DefaultOutputModes: []string{modeText},
9298
Capabilities: a2a.AgentCapabilities{Streaming: true, ExtendedAgentCard: true},
9399
SupportedInterfaces: []*a2a.AgentInterface{
94100
{
95101
ProtocolBinding: a2a.TransportProtocolJSONRPC,
96102
ProtocolVersion: a2a.Version,
97-
URL: "http://localhost:9999",
103+
URL: serverURL,
98104
},
99105
},
100106
Skills: []a2a.AgentSkill{
@@ -108,8 +114,8 @@ func main() {
108114
privateKey,
109115
ProtectedHeader{
110116
Kid: kid,
111-
Alg: "ES256",
112-
Jku: "http://localhost:9999/public_keys.json",
117+
Alg: es256Alg,
118+
Jku: serverURL + "/public_keys.json",
113119
},
114120
)
115121

samples/go/agents/signing_and_verifying/signing.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import (
1414
// Sentinel errors for signature verification matching Python SDK exception types.
1515
var (
1616
ErrNoSignature = errors.New("AgentCard has no signatures to verify")
17-
ErrInvalidSignatures = errors.New("No valid signature found")
17+
ErrInvalidSignatures = errors.New("no valid signature found")
1818
)
1919

2020
// ProtectedHeader defines the protected header parameters for JWS (RFC 7515).
@@ -84,7 +84,7 @@ func canonicalizeAgentCard(card *a2a.AgentCard) ([]byte, error) {
8484
// createAgentCardSigner creates a function that signs an AgentCard and appends the signature.
8585
func createAgentCardSigner(privateKey *ecdsa.PrivateKey, protectedHeader ProtectedHeader) func(card *a2a.AgentCard) (*a2a.AgentCard, error) {
8686
if protectedHeader.Alg == "" {
87-
protectedHeader.Alg = "ES256"
87+
protectedHeader.Alg = es256Alg
8888
}
8989

9090
method := jwt.GetSigningMethod(protectedHeader.Alg)
@@ -145,7 +145,7 @@ func createSignatureVerifier(keyProvider KeyProvider, allowedAlgs []string) func
145145
continue
146146
}
147147
var protectedHeader ProtectedHeader
148-
if err := json.Unmarshal(protectedBytes, &protectedHeader); err != nil {
148+
if unmarshalErr := json.Unmarshal(protectedBytes, &protectedHeader); unmarshalErr != nil {
149149
continue
150150
}
151151

samples/go/agents/signing_and_verifying/test_client.go

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ func keyProvider(kid, jku string) (any, error) {
2222
return nil, fmt.Errorf("kid or jku missing")
2323
}
2424

25+
//nolint:gosec // JKU URL is dynamic by design per RFC 7515
2526
resp, err := http.Get(jku)
2627
if err != nil {
2728
return nil, fmt.Errorf("failed to fetch jku: %w", err)
@@ -38,8 +39,8 @@ func keyProvider(kid, jku string) (any, error) {
3839
}
3940

4041
var keys map[string]string
41-
if err := json.Unmarshal(body, &keys); err != nil {
42-
return nil, fmt.Errorf("failed to unmarshal keys JSON: %w", err)
42+
if unmarshalErr := json.Unmarshal(body, &keys); unmarshalErr != nil {
43+
return nil, fmt.Errorf("failed to unmarshal keys JSON: %w", unmarshalErr)
4344
}
4445

4546
pemStr, ok := keys[kid]
@@ -62,9 +63,9 @@ func keyProvider(kid, jku string) (any, error) {
6263

6364
func runTestClient() {
6465
ctx := context.Background()
65-
signatureVerifier := createSignatureVerifier(keyProvider, []string{"ES256"})
66+
signatureVerifier := createSignatureVerifier(keyProvider, []string{es256Alg})
6667

67-
baseURL := "http://localhost:9999"
68+
baseURL := serverURL
6869

6970
log.Printf("Attempting to fetch public agent card from: %s%s", baseURL, a2asrv.WellKnownAgentCardPath)
7071

@@ -76,12 +77,15 @@ func runTestClient() {
7677
}
7778

7879
// Verifies the AgentCard using signature_verifier function before returning it
79-
if err := signatureVerifier(publicCard); err != nil {
80-
log.Fatalf("Failed to verify public agent card signature: %v", err)
80+
if verifyErr := signatureVerifier(publicCard); verifyErr != nil {
81+
log.Fatalf("Failed to verify public agent card signature: %v", verifyErr)
8182
}
8283

8384
log.Println("Successfully fetched public agent card:")
84-
cardJSON, _ := json.MarshalIndent(publicCard, "", " ")
85+
cardJSON, err := json.MarshalIndent(publicCard, "", " ")
86+
if err != nil {
87+
log.Fatalf("Failed to marshal public agent card: %v", err)
88+
}
8589
log.Println(string(cardJSON))
8690
log.Println("\nUsing PUBLIC agent card for client initialization (default).")
8791

@@ -97,11 +101,14 @@ func runTestClient() {
97101
}
98102

99103
// Verifies the AgentCard using signature_verifier function before returning it
100-
if err := signatureVerifier(extendedCard); err != nil {
101-
log.Fatalf("Failed to verify extended agent card signature: %v", err)
104+
if verifyErr := signatureVerifier(extendedCard); verifyErr != nil {
105+
log.Fatalf("Failed to verify extended agent card signature: %v", verifyErr)
102106
}
103107

104108
fmt.Println("Fetched extended card:")
105-
extJSON, _ := json.MarshalIndent(extendedCard, "", " ")
109+
extJSON, err := json.MarshalIndent(extendedCard, "", " ")
110+
if err != nil {
111+
log.Fatalf("Failed to marshal extended agent card: %v", err)
112+
}
106113
fmt.Println(string(extJSON))
107114
}

0 commit comments

Comments
 (0)