Server
Communication Protocol Guide
Build CookieFarm protocol plugins to submit flags to the Flag Checker service, parse JSON responses, and handle errors reliably.
File Location and Starter Template
Create your protocol file in:
pkg/protocols
Use this starter:
//go:build ignore
package main
import (
"protocols"
)
// Submit sends flags to the Flag Checker service and returns parsed results.
func Submit(host string, teamToken string, flags []string) ([]models.ResponseProtocol, error) {
// Your implementation here
return nil, nil
}Note: The return type should be
[]models.ResponseProtocol.
Response Model
The checker response should map to:
type ResponseProtocol struct {
Msg string `json:"msg"` // Human-readable message (often includes the flag)
Flag string `json:"flag"` // Submitted flag
Status string `json:"status"` // ACCEPTED | DENIED | RESUBMIT | ERROR
}Expected JSON Response
The Flag Checker returns a JSON array, one object per submitted flag:
[
{
"msg": "[<flag>] <message>",
"flag": "<flag>",
"status": "ACCEPTED"
}
]status values
ACCEPTED— valid flag acceptedDENIED— invalid/duplicate/not acceptedRESUBMIT— temporary issue, retry laterERROR— internal/generic processing error
Submit Function Contract
func Submit(host string, token string, flags []string) ([]models.ResponseProtocol, error)Parameters
host: Flag Checker address (example:localhost:5000)token: team authentication tokenflags: list of flags to submit
Returns
[]models.ResponseProtocol: parsed checker result per flagerror: request/response/parsing error
Example Implementations
//go:build ignore
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"models"
"net/http"
"strings"
"protocols"
)
func Submit(url string, teamToken string, flags []string) ([]protocols.ResponseProtocol, error) {
jsonData, err := json.Marshal(flags)
if err != nil {
return nil, fmt.Errorf("error during marshalling: %w", err)
}
req, err := http.NewRequest(http.MethodPut, url, bytes.NewBuffer(jsonData))
if err != nil {
return nil, fmt.Errorf("error during request creation: %w", err)
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-Team-Token", teamToken)
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return nil, fmt.Errorf("error during request submission: %w", err)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("error during response reading: %w", err)
}
var responses []struct {
Status string `json:"status"` // Status of the response (e.g., "0", "1", "2" ,"3") see enum in pkg/models/models.go
Flag string `json:"flag"` // Flag string received from the flag checker service
Msg string `json:"msg"`
}
// logger.Debug("Raw body %s", string(body))
if err := json.Unmarshal(body, &responses); err != nil {
return nil, fmt.Errorf("error during response parsing: %w", err)
}
var responsesParsed []protocols.ResponseProtocol = make([]protocols.ResponseProtocol, len(responses))
for i := range responses {
responsesParsed[i].Flag = responses[i].Flag
responsesParsed[i].Msg = strings.Split(responses[i].Msg, "]")[1]
switch responses[i].Status {
case "ACCEPTED":
responsesParsed[i].Status = models.StatusAccepted
case "DENIED":
responsesParsed[i].Status = models.StatusDenied
case "Error":
responsesParsed[i].Status = models.StatusError
default:
responsesParsed[i].Status = models.StatusNotValid
}
}
return responsesParsed, nil
}Build as a Go Plugin
Compile your protocol into a .so plugin:
go build -buildmode=plugin -o <name>.so <name>.go-buildmode=plugin: builds a runtime-loadable plugin<name>.so: output plugin<name>.go: source file
Error Handling Checklist
Your implementation should handle:
- network failures (checker unreachable/timeouts)
- invalid or malformed response bodies
- JSON unmarshal errors
On failure, return:
nilresponse- non-nil
error
Final Notes
- Ensure the Flag Checker is reachable at the configured
host. - Always send a valid team token.
- Keep response parsing strict to avoid silent failures.
- Prefer clear wrapped errors (
fmt.Errorf("...: %w", err)) for easier debugging.
How is this guide?