Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Project Overview

This is the OWASP Go Secure Coding Practices Guide - a GitBook-based documentation project providing security guidance for Go web application developers. The book follows the OWASP Secure Coding Practices Quick Reference Guide.

## Build Commands

```bash
# Install dependencies and build all formats (PDF, ePub, Mobi, DOCX)
npm i && node_modules/.bin/gitbook install && npm run build

# Live preview with hot reload
npm run serve

# Build individual formats
npm run build:pdf
npm run build:epub
npm run build:mobi
npm run build:docx

# Build using Docker (alternative)
docker-compose run -u node:node --rm build
```

## Project Structure

- `src/` - All book content in Markdown format
- `src/SUMMARY.md` - Book table of contents (defines chapter order)
- `src/README.md` - Book introduction
- `dist/` - Generated output files (PDF, ePub, Mobi)
- `book.json` - GitBook configuration
- `.go` files in `src/` subdirectories - Example code snippets referenced by chapters

## Content Organization

Book chapters follow OWASP security categories:
- Input Validation, Output Encoding
- Authentication/Password Management, Session Management
- Access Control, Cryptographic Practices
- Error Handling/Logging, Data Protection
- Communication Security, System Configuration
- Database Security, File Management, Memory Management
- General Coding Practices (CSRF, Regex)

## Git Flow

This project uses git-flow branching model:
- Features: `git flow feature start <name>` → PR to `develop`
- Hotfixes: `git flow hotfix start` → applies to both `develop` and `master`
- Releases are handled by project owner from `develop` to `master`
16 changes: 15 additions & 1 deletion src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,35 +5,49 @@ Summary
* [Input Validation](input-validation/README.md)
* [Validation](input-validation/validation.md)
* [Sanitization](input-validation/sanitization.md)
* [Command Injection](input-validation/command-injection.md)
* [Output Encoding](output-encoding/README.md)
* [XSS - Cross-Site Scripting](output-encoding/cross-site-scripting.md)
* [SQL Injection](output-encoding/sql-injection.md)
* [Content Security Policy](output-encoding/content-security-policy.md)
* [Authentication and Password Management](authentication-password-management/README.md)
* [Communicating authentication data](authentication-password-management/communicating-authentication-data.md)
* [Validation and Storage](authentication-password-management/validation-and-storage.md)
* [Password policies](authentication-password-management/password-policies.md)
* [Passkeys and WebAuthn](authentication-password-management/passkeys.md)
* [Other guidelines](authentication-password-management/other-guidelines.md)
* [Session Management](session-management/README.md)
* [Access Control](access-control/README.md)
* [Rate Limiting](access-control/rate-limiting.md)
* [Cryptographic Practices](cryptographic-practices/README.md)
* [Pseudo-Random Generators](cryptographic-practices/pseudo-random-generators.md)
* [Error Handling and Logging](error-handling-logging/README.md)
* [Error Handling](error-handling-logging/error-handling.md)
* [Logging](error-handling-logging/logging.md)
* [Context Timeouts](error-handling-logging/context-timeouts.md)
* [Data Protection](data-protection/README.md)
* [Secrets Management](data-protection/secrets-management.md)
* [Communication Security](communication-security/README.md)
* [HTTP/TLS](communication-security/http-tls.md)
* [HTTP Server Security](communication-security/http-server-security.md)
* [CORS Security](communication-security/cors-security.md)
* [WebSockets](communication-security/websockets.md)
* [System Configuration](system-configuration/README.md)
* [Container Security](system-configuration/container-security.md)
* [Database Security](database-security/README.md)
* [Connections](database-security/connections.md)
* [Authentication](database-security/authentication.md)
* [Parameterized Queries](database-security/parameterized-queries.md)
* [Stored Procedures](database-security/stored-procedures.md)
* [File Management](file-management/README.md)
* [Path Traversal](file-management/path-traversal.md)
* [Memory Management](memory-management/README.md)
* General Coding Practices
* [General Coding Practices](general-coding-practices/README.md)
* [Cross-Site Request Forgery](general-coding-practices/cross-site-request-forgery.md)
* [Regular Expressions](general-coding-practices/regular-expressions.md)
* [Security Tooling](security-tooling/README.md)
* [Development Tools](development-tools/README.md)
* [Claude Code Security Development](development-tools/claude-code-security.md)
* [Security Scanning Integration](development-tools/security-scanning.md)
* [How To Contribute](howto-contribute.md)
* [Final Notes](final-notes.md)
55 changes: 38 additions & 17 deletions src/access-control/URL.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ import (
"fmt"
"log"
"net/http"
"os"
"time"

"github.com/dgrijalva/jwt-go" //JWT is not in the native Go packages
"github.com/golang-jwt/jwt/v5" // Maintained JWT library (replaces deprecated dgrijalva/jwt-go)
)

type Key int
Expand All @@ -17,7 +18,17 @@ const MyKey Key = 0
// JWT schema of the data it will store
type Claims struct {
Username string `json:"username"`
jwt.StandardClaims
jwt.RegisteredClaims
}

// getJWTSecret retrieves the JWT secret from environment variables.
// SECURITY: Never hardcode secrets in source code.
func getJWTSecret() []byte {
secret := os.Getenv("JWT_SECRET")
if secret == "" {
log.Fatal("JWT_SECRET environment variable is required")
}
return []byte(secret)
}

func Homepage(res http.ResponseWriter, req *http.Request) {
Expand All @@ -30,28 +41,38 @@ func Homepage(res http.ResponseWriter, req *http.Request) {

// create a JWT and put in the clients cookie
func setToken(res http.ResponseWriter, req *http.Request) {
//30m Expiration for non-sensitive applications - OWSAP
expireToken := time.Now().Add(time.Minute * 30).Unix()
// 30m Expiration for non-sensitive applications - OWASP
expireCookie := time.Now().Add(time.Minute * 30)

//token Claims
// token Claims using jwt/v5 RegisteredClaims
claims := Claims{
"TestUser",
jwt.StandardClaims{
ExpiresAt: expireToken,
Username: "TestUser",
RegisteredClaims: jwt.RegisteredClaims{
ExpiresAt: jwt.NewNumericDate(expireCookie),
Issuer: "localhost:9000",
},
}

token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
signedToken, _ := token.SignedString([]byte("secret"))

//Set Cookie parameters
//Expires - 30m
//HTTP only
//Path
//Domain
cookie := http.Cookie{Name: "Auth", Value: signedToken, Expires: expireCookie, HttpOnly: true, Path: "/", Domain: "127.0.0.1", Secure: true}
signedToken, err := token.SignedString(getJWTSecret())
if err != nil {
http.Error(res, "Internal server error", http.StatusInternalServerError)
log.Printf("Error signing token: %v", err)
return
}

// Set Cookie parameters
// SameSite attribute helps prevent CSRF attacks
cookie := http.Cookie{
Name: "Auth",
Value: signedToken,
Expires: expireCookie, // 30 min
HttpOnly: true, // Prevents JavaScript access
Path: "/",
Domain: "127.0.0.1",
Secure: true, // Only sent over HTTPS
SameSite: http.SameSiteStrictMode, // CSRF protection
}
http.SetCookie(res, &cookie)
http.Redirect(res, req, "/profile", http.StatusTemporaryRedirect)
}
Expand All @@ -71,7 +92,7 @@ func validate(page http.HandlerFunc) http.HandlerFunc {
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
return nil, fmt.Errorf("unexpected signing method")
}
return []byte("secret"), nil
return getJWTSecret(), nil
})
if err != nil {
res.Header().Set("Content-Type", "text/html")
Expand Down
Loading