本文へ移動
cccskills
無料GitHub で公開

go-security-pitfalls

Use when reviewing Go changes - net/http and Fiber handlers, database/sql and GORM queries, os/exec, filepath and os.Root, html/template, crypto, TLS and SSH clients, JSON binding

インストール方法を見る

含まれるファイル(1)

  • SKILL.md5.9 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

Go Security Pitfalls

Overview

Go removes whole classes of bugs (memory safety, implicit shell, unsafe default deserialization), which makes the remaining ones look innocent: a fmt.Sprintf in a query builder, a HasPrefix path check, a template.HTML conversion. Memory-safety findings in pure Go are excluded; unsafe and cgo are the exception.

1. SQL: database/sql, sqlx, GORM (CWE-89)

// ❌
db.QueryContext(ctx, fmt.Sprintf("SELECT * FROM tasks WHERE owner = '%s'", owner))
// ✅
db.QueryContext(ctx, "SELECT * FROM tasks WHERE owner = $1", owner)

GORM accepts raw SQL in more places than people expect:

// ❌ all of these take SQL text
db.Where(fmt.Sprintf("name = '%s'", name)).Find(&users)
db.Order(r.URL.Query().Get("sort")).Find(&users)   // ORDER BY injection
db.First(&user, r.PathValue("id"))                // a string id is used as an inline condition
db.Raw("SELECT … " + filter).Scan(&rows)
// ✅
db.Where("name = ?", name).Find(&users)
db.Order(clause.OrderByColumn{Column: clause.Column{Name: sortCols[key]}}).Find(&users)
db.First(&user, "id = ?", id)

2. Commands: os/exec (CWE-78, CWE-88)

exec.Command never invokes a shell — unless you pass sh -c. With separate args the risk is argument injection:

// ❌ shell
exec.Command("sh", "-c", "git clone "+repoURL).Run()
// ❌ no shell, but repoURL = "--upload-pack=…" is an option
exec.Command("git", "clone", repoURL, dir).Run()
// ✅
exec.Command("git", "clone", "--", repoURL, dir).Run()

Also check cmd.Env built from request data (NODE_OPTIONS, LD_PRELOAD, GIT_SSH_COMMAND — injection-and-dangerous-sinks).

3. Paths: filepath, os.Root (CWE-22)

// ❌ lexical check: a symlink inside base escapes it, and
//    "/srv/data-other/x" passes HasPrefix(p, "/srv/data")
p := filepath.Join(base, name)
if !strings.HasPrefix(p, base) { … }

// ✅ Go 1.24+: lookups confined to the root, symlinks included
root, err := os.OpenRoot(base)
f, err := root.Open(name)
// ✅ older Go: reject anything non-local before joining
if !filepath.IsLocal(name) { return errBadPath }

http.FileServer(http.Dir(dir)) blocks .. but follows symlinks inside dir and serves dotfiles — a finding when dir is the repo root or an upload directory. Archive extraction: check filepath.IsLocal(hdr.Name) per entry.

4. Templates (CWE-79)

  • html/template escapes by context; text/template does not — rendering HTML with text/template is XSS when data is user-controlled.
  • Conversions switch escaping off: template.HTML(userBio), template.JS(…), template.URL(…), template.HTMLAttr(…) on user data.
  • template.New("x").Parse(userText) — the user writes the template (server-side template injection; with registered funcs that touch the system, worse).

5. JSON Binding (CWE-915)

// ❌ the request decodes straight into the domain type, Role and OrgID included
var u domain.User
json.NewDecoder(r.Body).Decode(&u)
// ✅ a request DTO with only client-settable fields, mapped explicitly
var req struct{ Name, Email string }
json.NewDecoder(r.Body).Decode(&req)

encoding/json matches keys case-insensitively and lets the last duplicate win: a gateway or validator that checks "role" misses "ROLE". Relevant only when a different component validates the raw JSON.

6. Crypto and Transport (CWE-295, CWE-338)

  • math/rand / math/rand/v2 for tokens → crypto/rand (rand.Text() in Go 1.24+).
  • tls.Config{InsecureSkipVerify: true} on a production client.
  • ssh.InsecureIgnoreHostKey() → MITM on every SSH connection (CWE-322).
  • Secret comparison: subtle.ConstantTimeCompare / hmac.Equal (a note at most when missing).

7. HTTP Handlers and Middleware

  • A route added on the bare router/app instead of the authenticated group (security-diff-review-method).
  • http.Redirect(w, r, r.URL.Query().Get("next"), http.StatusFound) — open redirect; high confidence only.
  • Client IP from X-Forwarded-For or a Fiber/Echo/Gin proxy-header setting without a trusted-proxy list, used for an allowlist or an auth decision.
  • An error from the authorization lookup that falls through to the handler (fail open).
  • Outbound http.Client fetching user URLs: use a dialer Control check and Proxy: nil (ssrf-and-url-allowlists).

8. unsafe and cgo

unsafe.Pointer arithmetic, unsafe.Slice/unsafe.String over attacker-sized buffers, and C code reached through cgo are memory-unsafe again — trace sizes and lengths from input.

Common Mistakes

  • Reporting exec.Command(bin, args...) as shell injection.
  • Reporting db.Query("… $1", v) or GORM Where("x = ?", v) as SQL injection.
  • Reporting gopkg.in/yaml.v3 or encoding/gob as unsafe deserialization — they do not instantiate arbitrary types.
  • Reporting races between goroutines on non-security state, or integer-conversion lint hits (gosec G115) with no attacker-controlled size.

Red Flags

  • fmt.Sprintf feeding Query, Exec, Raw, Where, Order, Group, Having.
  • "sh", "-c" / "bash", "-c" in exec.Command.
  • strings.HasPrefix on a joined path.
  • template.HTML( around anything not a constant.
  • InsecureSkipVerify: true, InsecureIgnoreHostKey(), math/rand near "token" or "secret".

References (names and links only)

Go security best practices · os.Root (Go 1.24) · gosec rules · GORM security · govulncheck

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

同じリポジトリのスキル

概要と使いどころ

Use when writing acceptance criteria for a task - express each as an observable Given/When/Then that QA can execute, including negative cases

日本語の概要は準備中です。原文の説明を表示しています。

makifbaysal/tasktrooper1122026年10月11日 更新

Use when the diff adds or changes an endpoint, resolver, RPC, job or query that takes an object id, a role check, a request binding or a tenant filter - BOLA/IDOR, function-level authorization, mass assignment and tenant scoping

日本語の概要は準備中です。原文の説明を表示しています。

makifbaysal/tasktrooper1122026年10月11日 更新

Use on every UI change - semantic HTML, labels for controls, keyboard-navigable dialogs/menus, visible focus, and never color as the only signal

日本語の概要は準備中です。原文の説明を表示しています。

makifbaysal/tasktrooper1122026年10月11日 更新

Use when a task changes any screen, form, dialog, menu or control - Lighthouse/axe scan of the changed screens, a keyboard walk, and the thresholds that fail a task

日本語の概要は準備中です。原文の説明を表示しています。

makifbaysal/tasktrooper1122026年10月11日 更新

How to work a task returned with review, QA or UAT findings. Use when a task is in need_revision or PR review comments are in your context.

日本語の概要は準備中です。原文の説明を表示しています。

makifbaysal/tasktrooper1122026年10月11日 更新

Use when deciding whether a request needs an analiz task before implementation - the conditions that require the architect's analysis versus going straight to implementation

日本語の概要は準備中です。原文の説明を表示しています。

makifbaysal/tasktrooper1122026年10月11日 更新

makifbaysal のスキルをすべて見る

このスキルの問題を報告する