diff --git a/.github/ISSUE_TEMPLATE/bug.yml b/.github/ISSUE_TEMPLATE/bug.yml new file mode 100644 index 0000000..01d20a8 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug.yml @@ -0,0 +1,67 @@ +name: Bug report +description: Report incorrect interpreter or CLI behavior +title: "" +labels: + - bug +body: + - type: markdown + attributes: + value: | + Thanks for helping improve go-basic. Please provide a small BASIC program that reproduces the problem. + - type: textarea + id: program + attributes: + label: Reproduction program + description: Paste the smallest BASIC source that demonstrates the problem. + render: basic + validations: + required: true + - type: input + id: command + attributes: + label: Command + description: Include any flags, such as `-seed` or `-max-statements`. + placeholder: go-basic -seed 1 program.bas + validations: + required: true + - type: textarea + id: actual + attributes: + label: Actual behavior + description: Include the complete output or diagnostic. + validations: + required: true + - type: textarea + id: expected + attributes: + label: Expected behavior + description: Explain what you expected and, when relevant, which BASIC dialect or source supports that expectation. + validations: + required: true + - type: input + id: version + attributes: + label: go-basic version + description: Run `go-basic -version`, or provide the commit SHA for a source build. + validations: + required: true + - type: input + id: environment + attributes: + label: Environment + description: Include operating system and architecture; include `go version` for source builds. + placeholder: macOS 15 arm64; go1.26.6 + validations: + required: true + - type: textarea + id: context + attributes: + label: Additional context + description: Add any other details that may help reproduce or diagnose the problem. + - type: checkboxes + id: conduct + attributes: + label: Code of Conduct + options: + - label: I agree to follow the repository's Code of Conduct. + required: true diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..3ba13e0 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1 @@ +blank_issues_enabled: false diff --git a/.github/ISSUE_TEMPLATE/feature.yml b/.github/ISSUE_TEMPLATE/feature.yml new file mode 100644 index 0000000..aa6c2a7 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature.yml @@ -0,0 +1,37 @@ +name: Feature request +description: Propose a focused language, CLI, compatibility, or tooling improvement +title: "" +labels: + - enhancement +body: + - type: textarea + id: problem + attributes: + label: Problem or use case + description: What is difficult or impossible today, and who would benefit? + validations: + required: true + - type: textarea + id: proposal + attributes: + label: Proposed behavior + description: Describe the smallest useful change and show example BASIC or CLI behavior when applicable. + validations: + required: true + - type: textarea + id: compatibility + attributes: + label: Compatibility evidence + description: For language changes, identify the BASIC dialect, historical program, or corpus source that motivates the behavior. + - type: textarea + id: alternatives + attributes: + label: Alternatives considered + description: Describe workarounds or other designs you considered. + - type: checkboxes + id: conduct + attributes: + label: Code of Conduct + options: + - label: I agree to follow the repository's Code of Conduct. + required: true diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..0bfac39 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,23 @@ +## Summary + + + +## Related issue + + + +## Behavior + + + +## Validation + + + +- [ ] Added or updated behavior-focused tests where applicable. +- [ ] Ran `make fmt`. +- [ ] Ran `make check`. +- [ ] Ran `make fuzz` when lexer or parser behavior changed. +- [ ] Ran `make corpus-smoke` and `make corpus-playable` when compatibility behavior changed. +- [ ] Ran `make vuln`. +- [ ] Updated user-facing documentation where applicable. diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8fd33c6..b464b29 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,16 +16,16 @@ jobs: timeout-minutes: 20 steps: - name: Check out repository - uses: actions/checkout@v7 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 - name: Set up Go - uses: actions/setup-go@v7 + uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7 with: go-version-file: go.mod cache: false - name: Cache pinned BASIC corpus - uses: actions/cache@v6 + uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6 with: path: .cache/basic-computer-games key: basic-computer-games-5301155192d91d74d337899cecc59dbda59c4c17 @@ -56,16 +56,16 @@ jobs: timeout-minutes: 10 steps: - name: Check out repository - uses: actions/checkout@v7 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 - name: Set up Go - uses: actions/setup-go@v7 + uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7 with: go-version-file: go.mod cache: false - name: Run golangci-lint - uses: golangci/golangci-lint-action@v9 + uses: golangci/golangci-lint-action@ba0d7d2ec06a0ea1cb5fa41b2e4a3ab91d21278a # v9 with: version: v2.12.2 @@ -75,10 +75,10 @@ jobs: timeout-minutes: 10 steps: - name: Check out repository - uses: actions/checkout@v7 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 - name: Set up Go - uses: actions/setup-go@v7 + uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7 with: go-version-file: go.mod cache: false diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 68973a6..1060306 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -15,16 +15,16 @@ jobs: timeout-minutes: 30 steps: - name: Check out repository - uses: actions/checkout@v7 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 - name: Set up Go - uses: actions/setup-go@v7 + uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7 with: go-version-file: go.mod cache: false - name: Cache pinned BASIC corpus - uses: actions/cache@v6 + uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6 with: path: .cache/basic-computer-games key: basic-computer-games-5301155192d91d74d337899cecc59dbda59c4c17 @@ -45,7 +45,7 @@ jobs: run: make release-check VERSION=${{ github.ref_name }} - name: Publish GitHub release - uses: softprops/action-gh-release@v3 + uses: softprops/action-gh-release@3d0d9888cb7fd7b750713d6e236d1fcb99157228 # v3 with: fail_on_unmatched_files: true generate_release_notes: true diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..59588f3 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,41 @@ +# Code of Conduct + +## Our commitment + +We are committed to making participation in go-basic welcoming, respectful, +and free from harassment for everyone, regardless of background, identity, +experience, or level of technical expertise. + +## Expected behavior + +Participants are expected to: + +- communicate with empathy and respect; +- give and accept constructive, specific feedback; +- focus disagreements on ideas and observable behavior; +- respect privacy and differing experience levels; and +- take responsibility for mistakes and help repair their impact. + +## Unacceptable behavior + +Harassment, discrimination, threats, sexualized attention, personal attacks, +doxing, sustained disruption, and publishing another person's private +information without permission are not acceptable. + +## Scope + +This policy applies in repository issues, pull requests, reviews, discussions, +and other spaces where someone is representing the project. + +## Reporting and enforcement + +Use GitHub's +[Report abuse or spam](https://docs.github.com/en/communities/maintaining-your-safety-on-github/reporting-abuse-or-spam) +tools to report conduct that violates GitHub policy. For project-specific +concerns, contact the repository owner through the contact information on +their [GitHub profile](https://github.com/scottdensmore). Do not disclose +sensitive personal information in a public issue. + +Maintainers may edit or remove contributions and may temporarily or +permanently restrict participation when behavior conflicts with this policy. +Reports will be handled as privately and impartially as practical. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index fd99418..592ea92 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -84,3 +84,10 @@ include: Unsupported or malformed BASIC must return an actionable diagnostic. Do not silently skip syntax or introduce panic paths. + +## Community and security + +Participation in project spaces is governed by the +[Code of Conduct](CODE_OF_CONDUCT.md). Report suspected vulnerabilities through +the private process in the [Security Policy](SECURITY.md), not through a public +issue. diff --git a/README.md b/README.md index 6f05389..12a904a 100644 --- a/README.md +++ b/README.md @@ -56,6 +56,8 @@ Hello World | [Language reference](docs/language-reference.md) | Supported syntax, statements, operators, functions, and extensions | | [Compatibility](docs/compatibility.md) | Pinned corpus, acceptance tiers, results, and known upstream exception | | [Contributing](CONTRIBUTING.md) | Development workflow, testing expectations, and pull requests | +| [Security](SECURITY.md) | Supported versions, private reporting, trust boundaries, and limitations | +| [Code of Conduct](CODE_OF_CONDUCT.md) | Expected behavior and reporting options for project spaces | ## Supported at a glance diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..0db585e --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,105 @@ +# Security Policy + +## Supported Versions + +Security fixes target the `main` branch and, when practical, the latest published +release. Older releases are not supported. Users should reproduce a suspected +issue against the latest release or `main` before reporting it. + +## Reporting a Vulnerability + +Report suspected vulnerabilities through +[GitHub private vulnerability reporting](https://github.com/scottdensmore/go-basic/security/advisories/new). +Do not disclose security-sensitive details in a public issue. + +Include the affected version or commit, operating system and architecture, +realistic impact, reproduction steps or a minimal BASIC program, and any known +mitigations. Reports should avoid unrelated personal data or secrets. + +The maintainer will aim to acknowledge a report within seven days, confirm +whether it is accepted, and coordinate remediation and disclosure when +appropriate. + +## System and Scope + +This policy covers: + +- the `go-basic` command-line application; +- the lexer, parser, structured-source lowering, and evaluator under + `pkg/interpreter`; +- pinned corpus acquisition and execution tooling; +- GitHub Actions workflows and published release artifacts. + +go-basic is a local command-line program, not a network service. It reads a +source file selected by the user, may read program input from standard input, +and writes program output and diagnostics to the provided streams. + +## Threat Model and Trust Boundaries + +BASIC source, program input, corpus archives, archive paths, and command-line +arguments are potentially attacker-controlled. Important assets include the +host filesystem and processes, developer and CI credentials, build integrity, +and published release artifacts. + +Running a BASIC program intentionally grants it CPU time, memory, and output +within the go-basic process. It must not grant access to unrelated host +capabilities. + +## Security Invariants + +The following properties must hold: + +- BASIC programs cannot read or modify arbitrary host files, start processes, + or initiate network connections. +- Malformed source and input return actionable errors rather than panicking or + corrupting interpreter state. +- Array dimensions and other attacker-controlled allocations remain validated + and bounded. +- Corpus extraction cannot escape its target directory, follow archive + symlinks, or overwrite existing files. +- Corpus and release workflows use pinned inputs, least-privilege permissions, + and immutable GitHub Action revisions. +- Release artifacts are produced only after the repository verification gates + pass. + +## Reportable Findings and Severity Context + +Reportable findings include: + +- arbitrary file access, process execution, network access, or directory + traversal caused by BASIC input or a corpus archive; +- a panic or disproportionate resource exhaustion caused by a small, + well-formed input that bypasses documented limits; +- a CI or release-integrity weakness that creates a realistic path to modifying + published artifacts or exposing credentials; and +- validation failures that cross the documented interpreter or tooling trust + boundaries. + +Severity depends on realistic reachability and impact. An issue requiring a user +to explicitly execute a malicious local program is generally less severe than a +repository or release compromise affecting downstream users. + +## Out of Scope + +The following are not security findings without additional security impact: + +- BASIC dialect incompatibilities or incorrect game behavior; +- upstream corpus defects; +- intentionally non-terminating programs run without `-max-statements`; +- large or continuous output explicitly produced by the BASIC program; and +- findings that require an already-compromised host, GitHub account, or build + runner without crossing another boundary. + +## Known Limitations and Compensating Controls + +go-basic is an interpreter, not a security sandbox. Run untrusted programs +inside an operating-system sandbox when stronger isolation is required. + +Execution is unlimited unless the caller supplies `-max-statements`, and program +output is not capped. The corpus acceptance tools apply deterministic statement +and wall-clock bounds. + +The corpus downloader selects an immutable upstream commit over HTTPS and +restricts extraction to expected regular BASIC files. The commit pin stabilizes +source selection but is not an independent cryptographic signature over the +downloaded archive.