@kevinrabun/judges 3.23.6 → 3.23.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1586,6 +1586,562 @@ app.post("/api/v1/login", async (req, res) => {
1586
1586
  category: "clean",
1587
1587
  difficulty: "hard",
1588
1588
  },
1589
+ // ── FP Benchmark Corpus — Multi-Language Clean Code ──────────────────────
1590
+ // These cases are well-written code that should NOT trigger findings.
1591
+ // They measure the false positive rate across languages.
1592
+ // ────────────────────────────────────────────────────────────────────────────
1593
+ // ── Clean Python: FastAPI with Pydantic validation ──
1594
+ {
1595
+ id: "clean-python-fastapi",
1596
+ description: "Well-structured FastAPI endpoint with Pydantic validation, auth, and error handling",
1597
+ language: "python",
1598
+ code: `from fastapi import FastAPI, Depends, HTTPException, status
1599
+ from fastapi.security import OAuth2PasswordBearer
1600
+ from pydantic import BaseModel, EmailStr, Field
1601
+ from slowapi import Limiter
1602
+ from slowapi.util import get_remote_address
1603
+ import logging
1604
+ import secrets
1605
+
1606
+ app = FastAPI()
1607
+ limiter = Limiter(key_func=get_remote_address)
1608
+ oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
1609
+ logger = logging.getLogger(__name__)
1610
+
1611
+ class UserCreate(BaseModel):
1612
+ email: EmailStr
1613
+ password: str = Field(min_length=12, max_length=128)
1614
+ name: str = Field(min_length=1, max_length=200)
1615
+
1616
+ @app.post("/api/v1/users", status_code=status.HTTP_201_CREATED)
1617
+ @limiter.limit("10/minute")
1618
+ async def create_user(user: UserCreate, token: str = Depends(oauth2_scheme)):
1619
+ current_user = await verify_token(token)
1620
+ if not current_user.is_admin:
1621
+ raise HTTPException(status_code=403, detail="Admin access required")
1622
+ hashed = bcrypt.hashpw(user.password.encode(), bcrypt.gensalt())
1623
+ new_user = await db.users.create(email=user.email, password_hash=hashed, name=user.name)
1624
+ logger.info("User created: %s by admin %s", new_user.id, current_user.id)
1625
+ return {"id": new_user.id, "email": new_user.email}`,
1626
+ expectedRuleIds: [],
1627
+ unexpectedRuleIds: ["CYBER-001", "CYBER-002", "AUTH-001", "SEC-001", "RATE-001", "DATA-001"],
1628
+ category: "clean",
1629
+ difficulty: "hard",
1630
+ },
1631
+ // ── Clean Go: HTTP handler with proper error handling ──
1632
+ {
1633
+ id: "clean-go-handler",
1634
+ description: "Well-structured Go HTTP handler with parameterized queries, auth, and logging",
1635
+ language: "go",
1636
+ code: `package handlers
1637
+
1638
+ import (
1639
+ "encoding/json"
1640
+ "log/slog"
1641
+ "net/http"
1642
+ "github.com/go-chi/chi/v5"
1643
+ "github.com/jmoiron/sqlx"
1644
+ )
1645
+
1646
+ type UserHandler struct {
1647
+ db *sqlx.DB
1648
+ logger *slog.Logger
1649
+ }
1650
+
1651
+ type CreateUserRequest struct {
1652
+ Email string \`json:"email" validate:"required,email"\`
1653
+ Name string \`json:"name" validate:"required,min=1,max=200"\`
1654
+ }
1655
+
1656
+ func (h *UserHandler) GetUser(w http.ResponseWriter, r *http.Request) {
1657
+ userID := chi.URLParam(r, "id")
1658
+ if userID == "" {
1659
+ http.Error(w, "missing user id", http.StatusBadRequest)
1660
+ return
1661
+ }
1662
+ var user User
1663
+ err := h.db.QueryRowContext(r.Context(), "SELECT id, email, name FROM users WHERE id = $1", userID).Scan(&user.ID, &user.Email, &user.Name)
1664
+ if err != nil {
1665
+ h.logger.Error("failed to fetch user", "error", err, "user_id", userID)
1666
+ http.Error(w, "user not found", http.StatusNotFound)
1667
+ return
1668
+ }
1669
+ w.Header().Set("Content-Type", "application/json")
1670
+ json.NewEncoder(w).Encode(user)
1671
+ }`,
1672
+ expectedRuleIds: [],
1673
+ unexpectedRuleIds: ["CYBER-001", "CYBER-002", "SEC-001", "ERR-001"],
1674
+ category: "clean",
1675
+ difficulty: "hard",
1676
+ },
1677
+ // ── Clean Rust: Safe web handler ──
1678
+ {
1679
+ id: "clean-rust-handler",
1680
+ description: "Well-structured Rust Actix-web handler with validation and error types",
1681
+ language: "rust",
1682
+ code: `use actix_web::{web, HttpResponse, Result};
1683
+ use serde::{Deserialize, Serialize};
1684
+ use sqlx::PgPool;
1685
+ use validator::Validate;
1686
+ use tracing::{info, error};
1687
+
1688
+ #[derive(Deserialize, Validate)]
1689
+ pub struct CreateItemRequest {
1690
+ #[validate(length(min = 1, max = 200))]
1691
+ pub name: String,
1692
+ #[validate(range(min = 0.01, max = 999999.99))]
1693
+ pub price: f64,
1694
+ }
1695
+
1696
+ #[derive(Serialize)]
1697
+ pub struct ItemResponse {
1698
+ pub id: i64,
1699
+ pub name: String,
1700
+ pub price: f64,
1701
+ }
1702
+
1703
+ pub async fn create_item(
1704
+ pool: web::Data<PgPool>,
1705
+ body: web::Json<CreateItemRequest>,
1706
+ ) -> Result<HttpResponse> {
1707
+ body.validate().map_err(|e| {
1708
+ actix_web::error::ErrorBadRequest(format!("Validation error: {}", e))
1709
+ })?;
1710
+ let row = sqlx::query_as!(
1711
+ ItemResponse,
1712
+ "INSERT INTO items (name, price) VALUES ($1, $2) RETURNING id, name, price",
1713
+ body.name,
1714
+ body.price,
1715
+ )
1716
+ .fetch_one(pool.get_ref())
1717
+ .await
1718
+ .map_err(|e| {
1719
+ error!("DB insert failed: {}", e);
1720
+ actix_web::error::ErrorInternalServerError("Failed to create item")
1721
+ })?;
1722
+ info!(item_id = row.id, "Item created");
1723
+ Ok(HttpResponse::Created().json(row))
1724
+ }`,
1725
+ expectedRuleIds: [],
1726
+ unexpectedRuleIds: ["CYBER-001", "CYBER-002", "SEC-001", "ERR-001"],
1727
+ category: "clean",
1728
+ difficulty: "hard",
1729
+ },
1730
+ // ── Clean Java: Spring Boot controller with validation ──
1731
+ {
1732
+ id: "clean-java-spring",
1733
+ description: "Well-structured Spring Boot REST controller with validation and auth",
1734
+ language: "java",
1735
+ code: `import org.springframework.web.bind.annotation.*;
1736
+ import org.springframework.http.ResponseEntity;
1737
+ import org.springframework.security.access.prepost.PreAuthorize;
1738
+ import javax.validation.Valid;
1739
+ import org.slf4j.Logger;
1740
+ import org.slf4j.LoggerFactory;
1741
+
1742
+ @RestController
1743
+ @RequestMapping("/api/v1/products")
1744
+ public class ProductController {
1745
+ private static final Logger log = LoggerFactory.getLogger(ProductController.class);
1746
+ private final ProductService productService;
1747
+
1748
+ public ProductController(ProductService productService) {
1749
+ this.productService = productService;
1750
+ }
1751
+
1752
+ @GetMapping("/{id}")
1753
+ public ResponseEntity<ProductDTO> getProduct(@PathVariable Long id) {
1754
+ return productService.findById(id)
1755
+ .map(ResponseEntity::ok)
1756
+ .orElse(ResponseEntity.notFound().build());
1757
+ }
1758
+
1759
+ @PostMapping
1760
+ @PreAuthorize("hasRole('ADMIN')")
1761
+ public ResponseEntity<ProductDTO> createProduct(@Valid @RequestBody CreateProductRequest request) {
1762
+ log.info("Creating product: {}", request.getName());
1763
+ ProductDTO created = productService.create(request);
1764
+ return ResponseEntity.status(201).body(created);
1765
+ }
1766
+
1767
+ @DeleteMapping("/{id}")
1768
+ @PreAuthorize("hasRole('ADMIN')")
1769
+ public ResponseEntity<Void> deleteProduct(@PathVariable Long id) {
1770
+ log.info("Deleting product: {}", id);
1771
+ productService.delete(id);
1772
+ return ResponseEntity.noContent().build();
1773
+ }
1774
+ }`,
1775
+ expectedRuleIds: [],
1776
+ unexpectedRuleIds: ["CYBER-001", "CYBER-002", "AUTH-001", "SEC-001"],
1777
+ category: "clean",
1778
+ difficulty: "hard",
1779
+ },
1780
+ // ── Clean C#: ASP.NET Core controller ──
1781
+ {
1782
+ id: "clean-csharp-aspnet",
1783
+ description: "Well-structured ASP.NET Core controller with EF Core parameterized queries",
1784
+ language: "csharp",
1785
+ code: `using Microsoft.AspNetCore.Mvc;
1786
+ using Microsoft.AspNetCore.Authorization;
1787
+ using Microsoft.EntityFrameworkCore;
1788
+ using Microsoft.Extensions.Logging;
1789
+ using FluentValidation;
1790
+
1791
+ [ApiController]
1792
+ [Route("api/v1/[controller]")]
1793
+ [Authorize]
1794
+ public class OrdersController : ControllerBase
1795
+ {
1796
+ private readonly AppDbContext _db;
1797
+ private readonly ILogger<OrdersController> _logger;
1798
+ private readonly IValidator<CreateOrderRequest> _validator;
1799
+
1800
+ public OrdersController(AppDbContext db, ILogger<OrdersController> logger, IValidator<CreateOrderRequest> validator)
1801
+ {
1802
+ _db = db;
1803
+ _logger = logger;
1804
+ _validator = validator;
1805
+ }
1806
+
1807
+ [HttpGet("{id}")]
1808
+ public async Task<IActionResult> GetOrder(int id)
1809
+ {
1810
+ var order = await _db.Orders
1811
+ .Where(o => o.Id == id && o.UserId == User.GetUserId())
1812
+ .FirstOrDefaultAsync();
1813
+ if (order == null) return NotFound();
1814
+ return Ok(order);
1815
+ }
1816
+
1817
+ [HttpPost]
1818
+ public async Task<IActionResult> CreateOrder([FromBody] CreateOrderRequest request)
1819
+ {
1820
+ var validation = await _validator.ValidateAsync(request);
1821
+ if (!validation.IsValid) return BadRequest(validation.Errors);
1822
+ var order = new Order { UserId = User.GetUserId(), Total = request.Total, Items = request.Items };
1823
+ _db.Orders.Add(order);
1824
+ await _db.SaveChangesAsync();
1825
+ _logger.LogInformation("Order {OrderId} created by user {UserId}", order.Id, User.GetUserId());
1826
+ return CreatedAtAction(nameof(GetOrder), new { id = order.Id }, order);
1827
+ }
1828
+ }`,
1829
+ expectedRuleIds: [],
1830
+ unexpectedRuleIds: ["CYBER-001", "CYBER-002", "AUTH-001", "SEC-001", "DATA-001"],
1831
+ category: "clean",
1832
+ difficulty: "hard",
1833
+ },
1834
+ // ── Clean TypeScript: Pure utility library (no server) ──
1835
+ {
1836
+ id: "clean-ts-utility-lib",
1837
+ description: "Pure TypeScript utility library — no server code, should have zero security findings",
1838
+ language: "typescript",
1839
+ code: `/**
1840
+ * A type-safe result type for error handling without exceptions.
1841
+ */
1842
+ export type Result<T, E = Error> = { ok: true; value: T } | { ok: false; error: E };
1843
+
1844
+ export function ok<T>(value: T): Result<T, never> {
1845
+ return { ok: true, value };
1846
+ }
1847
+
1848
+ export function err<E>(error: E): Result<never, E> {
1849
+ return { ok: false, error };
1850
+ }
1851
+
1852
+ export function map<T, U, E>(result: Result<T, E>, fn: (value: T) => U): Result<U, E> {
1853
+ return result.ok ? ok(fn(result.value)) : result;
1854
+ }
1855
+
1856
+ export function flatMap<T, U, E>(result: Result<T, E>, fn: (value: T) => Result<U, E>): Result<U, E> {
1857
+ return result.ok ? fn(result.value) : result;
1858
+ }
1859
+
1860
+ export function unwrapOr<T, E>(result: Result<T, E>, defaultValue: T): T {
1861
+ return result.ok ? result.value : defaultValue;
1862
+ }
1863
+
1864
+ /** Retry an async operation with exponential backoff. */
1865
+ export async function retry<T>(fn: () => Promise<T>, maxRetries = 3, baseDelay = 100): Promise<T> {
1866
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
1867
+ try {
1868
+ return await fn();
1869
+ } catch (error) {
1870
+ if (attempt === maxRetries) throw error;
1871
+ await new Promise((r) => setTimeout(r, baseDelay * Math.pow(2, attempt)));
1872
+ }
1873
+ }
1874
+ throw new Error("Unreachable");
1875
+ }`,
1876
+ expectedRuleIds: [],
1877
+ unexpectedRuleIds: ["CYBER-001", "CYBER-002", "SEC-001", "AUTH-001", "RATE-001", "ERR-001"],
1878
+ category: "clean",
1879
+ difficulty: "hard",
1880
+ },
1881
+ // ── Clean Terraform: Hardened AWS infrastructure ──
1882
+ {
1883
+ id: "clean-terraform-hardened",
1884
+ description: "Terraform with encryption, private access, and proper security groups",
1885
+ language: "hcl",
1886
+ code: `resource "aws_s3_bucket" "data" {
1887
+ bucket = "myapp-data-prod"
1888
+ }
1889
+
1890
+ resource "aws_s3_bucket_server_side_encryption_configuration" "data" {
1891
+ bucket = aws_s3_bucket.data.id
1892
+ rule {
1893
+ apply_server_side_encryption_by_default {
1894
+ sse_algorithm = "aws:kms"
1895
+ }
1896
+ }
1897
+ }
1898
+
1899
+ resource "aws_s3_bucket_public_access_block" "data" {
1900
+ bucket = aws_s3_bucket.data.id
1901
+ block_public_acls = true
1902
+ block_public_policy = true
1903
+ ignore_public_acls = true
1904
+ restrict_public_buckets = true
1905
+ }
1906
+
1907
+ resource "aws_db_instance" "main" {
1908
+ engine = "postgres"
1909
+ instance_class = "db.r6g.large"
1910
+ publicly_accessible = false
1911
+ storage_encrypted = true
1912
+ multi_az = true
1913
+ deletion_protection = true
1914
+ backup_retention_period = 7
1915
+ }
1916
+
1917
+ resource "aws_security_group" "web" {
1918
+ name = "web-sg"
1919
+ vpc_id = var.vpc_id
1920
+
1921
+ ingress {
1922
+ from_port = 443
1923
+ to_port = 443
1924
+ protocol = "tcp"
1925
+ cidr_blocks = [var.allowed_cidr]
1926
+ }
1927
+
1928
+ egress {
1929
+ from_port = 0
1930
+ to_port = 0
1931
+ protocol = "-1"
1932
+ cidr_blocks = ["0.0.0.0/0"]
1933
+ }
1934
+ }`,
1935
+ expectedRuleIds: [],
1936
+ unexpectedRuleIds: ["IAC-001", "SEC-001", "CYBER-001", "DATA-001"],
1937
+ category: "clean",
1938
+ difficulty: "hard",
1939
+ },
1940
+ // ── Clean Python: Data processing script (not a server) ──
1941
+ {
1942
+ id: "clean-python-data-script",
1943
+ description: "Python data processing script — no web endpoints, should not flag server concerns",
1944
+ language: "python",
1945
+ code: `"""Data pipeline for aggregating daily sales metrics."""
1946
+ import csv
1947
+ import logging
1948
+ from pathlib import Path
1949
+ from dataclasses import dataclass
1950
+ from typing import Iterator
1951
+
1952
+ logger = logging.getLogger(__name__)
1953
+
1954
+ @dataclass
1955
+ class SalesRecord:
1956
+ date: str
1957
+ product_id: str
1958
+ quantity: int
1959
+ unit_price: float
1960
+
1961
+ @property
1962
+ def total(self) -> float:
1963
+ return self.quantity * self.unit_price
1964
+
1965
+ def read_records(path: Path) -> Iterator[SalesRecord]:
1966
+ with path.open("r", encoding="utf-8") as f:
1967
+ reader = csv.DictReader(f)
1968
+ for row in reader:
1969
+ try:
1970
+ yield SalesRecord(
1971
+ date=row["date"],
1972
+ product_id=row["product_id"],
1973
+ quantity=int(row["quantity"]),
1974
+ unit_price=float(row["unit_price"]),
1975
+ )
1976
+ except (KeyError, ValueError) as e:
1977
+ logger.warning("Skipping invalid row: %s (%s)", row, e)
1978
+
1979
+ def aggregate_by_date(records: Iterator[SalesRecord]) -> dict[str, float]:
1980
+ totals: dict[str, float] = {}
1981
+ for record in records:
1982
+ totals[record.date] = totals.get(record.date, 0.0) + record.total
1983
+ return totals
1984
+
1985
+ if __name__ == "__main__":
1986
+ logging.basicConfig(level=logging.INFO)
1987
+ path = Path("data/sales.csv")
1988
+ if not path.exists():
1989
+ logger.error("File not found: %s", path)
1990
+ raise SystemExit(1)
1991
+ results = aggregate_by_date(read_records(path))
1992
+ for date, total in sorted(results.items()):
1993
+ logger.info("Date: %s, Total: $%.2f", date, total)`,
1994
+ expectedRuleIds: [],
1995
+ unexpectedRuleIds: ["CYBER-001", "CYBER-002", "SEC-001", "AUTH-001", "RATE-001"],
1996
+ category: "clean",
1997
+ difficulty: "hard",
1998
+ },
1999
+ // ── Clean Go: CLI tool (not a server) ──
2000
+ {
2001
+ id: "clean-go-cli-tool",
2002
+ description: "Go CLI tool — should not flag server-side security concerns",
2003
+ language: "go",
2004
+ code: `package main
2005
+
2006
+ import (
2007
+ "encoding/json"
2008
+ "flag"
2009
+ "fmt"
2010
+ "log"
2011
+ "os"
2012
+ "path/filepath"
2013
+ "sort"
2014
+ )
2015
+
2016
+ type Config struct {
2017
+ InputDir string \`json:"input_dir"\`
2018
+ OutputDir string \`json:"output_dir"\`
2019
+ Verbose bool \`json:"verbose"\`
2020
+ }
2021
+
2022
+ func loadConfig(path string) (*Config, error) {
2023
+ data, err := os.ReadFile(path)
2024
+ if err != nil {
2025
+ return nil, fmt.Errorf("read config: %w", err)
2026
+ }
2027
+ var cfg Config
2028
+ if err := json.Unmarshal(data, &cfg); err != nil {
2029
+ return nil, fmt.Errorf("parse config: %w", err)
2030
+ }
2031
+ return &cfg, nil
2032
+ }
2033
+
2034
+ func processFiles(cfg *Config) error {
2035
+ entries, err := os.ReadDir(cfg.InputDir)
2036
+ if err != nil {
2037
+ return fmt.Errorf("read dir: %w", err)
2038
+ }
2039
+ sort.Slice(entries, func(i, j int) bool { return entries[i].Name() < entries[j].Name() })
2040
+ for _, entry := range entries {
2041
+ if entry.IsDir() || filepath.Ext(entry.Name()) != ".json" {
2042
+ continue
2043
+ }
2044
+ src := filepath.Join(cfg.InputDir, entry.Name())
2045
+ dst := filepath.Join(cfg.OutputDir, entry.Name())
2046
+ if cfg.Verbose {
2047
+ log.Printf("Processing: %s -> %s", src, dst)
2048
+ }
2049
+ data, err := os.ReadFile(src)
2050
+ if err != nil {
2051
+ log.Printf("Warning: skip %s: %v", src, err)
2052
+ continue
2053
+ }
2054
+ if err := os.WriteFile(dst, data, 0644); err != nil {
2055
+ return fmt.Errorf("write %s: %w", dst, err)
2056
+ }
2057
+ }
2058
+ return nil
2059
+ }
2060
+
2061
+ func main() {
2062
+ configPath := flag.String("config", "config.json", "path to config file")
2063
+ flag.Parse()
2064
+ cfg, err := loadConfig(*configPath)
2065
+ if err != nil {
2066
+ log.Fatal(err)
2067
+ }
2068
+ if err := processFiles(cfg); err != nil {
2069
+ log.Fatal(err)
2070
+ }
2071
+ fmt.Println("Done.")
2072
+ }`,
2073
+ expectedRuleIds: [],
2074
+ unexpectedRuleIds: ["CYBER-001", "CYBER-002", "SEC-001", "AUTH-001", "RATE-001", "ERR-001"],
2075
+ category: "clean",
2076
+ difficulty: "hard",
2077
+ },
2078
+ // ── Clean TypeScript: React component (not a server) ──
2079
+ {
2080
+ id: "clean-ts-react-component",
2081
+ description: "React component with hooks — should not trigger server-side security findings",
2082
+ language: "typescript",
2083
+ code: `import React, { useState, useCallback, useMemo } from "react";
2084
+
2085
+ interface User {
2086
+ id: string;
2087
+ name: string;
2088
+ email: string;
2089
+ }
2090
+
2091
+ interface UserListProps {
2092
+ users: User[];
2093
+ onSelect: (user: User) => void;
2094
+ searchLabel?: string;
2095
+ }
2096
+
2097
+ export function UserList({ users, onSelect, searchLabel = "Search users" }: UserListProps): React.JSX.Element {
2098
+ const [filter, setFilter] = useState("");
2099
+
2100
+ const handleFilterChange = useCallback(
2101
+ (event: React.ChangeEvent<HTMLInputElement>) => {
2102
+ setFilter(event.target.value);
2103
+ },
2104
+ [],
2105
+ );
2106
+
2107
+ const filteredUsers = useMemo(() => {
2108
+ const lower = filter.toLowerCase();
2109
+ return users.filter(
2110
+ (u) => u.name.toLowerCase().includes(lower) || u.email.toLowerCase().includes(lower),
2111
+ );
2112
+ }, [users, filter]);
2113
+
2114
+ return (
2115
+ <div role="search" aria-label={searchLabel}>
2116
+ <label htmlFor="user-search">{searchLabel}</label>
2117
+ <input
2118
+ id="user-search"
2119
+ type="text"
2120
+ value={filter}
2121
+ onChange={handleFilterChange}
2122
+ placeholder="Type to filter..."
2123
+ aria-describedby="user-count"
2124
+ />
2125
+ <p id="user-count" aria-live="polite">
2126
+ {filteredUsers.length} users found
2127
+ </p>
2128
+ <ul role="list">
2129
+ {filteredUsers.map((user) => (
2130
+ <li key={user.id}>
2131
+ <button onClick={() => onSelect(user)} aria-label={\`Select \${user.name}\`}>
2132
+ {user.name} ({user.email})
2133
+ </button>
2134
+ </li>
2135
+ ))}
2136
+ </ul>
2137
+ </div>
2138
+ );
2139
+ }`,
2140
+ expectedRuleIds: [],
2141
+ unexpectedRuleIds: ["CYBER-001", "CYBER-002", "SEC-001", "AUTH-001", "A11Y-001"],
2142
+ category: "clean",
2143
+ difficulty: "hard",
2144
+ },
1589
2145
  ];
1590
2146
  // ─── Benchmark Runner ───────────────────────────────────────────────────────
1591
2147
  export function runBenchmarkSuite(cases, judgeId) {