Files
artex/CONTRIBUTING.en.md
dela 0335d572de
ci / go (push) Waiting to run
ci / go-db (agent) (push) Waiting to run
ci / go-db (config) (push) Waiting to run
ci / go-db (db) (push) Waiting to run
ci / go-db (evidence) (push) Waiting to run
ci / go-db (llmrec) (push) Waiting to run
ci / go-db (server) (push) Waiting to run
detections / detections (push) Waiting to run
web / web (push) Waiting to run
docs / links (push) Canceled after 0s
First Commit
2026-10-09 08:38:16 +08:00

19 KiB

Contributing

한국어 · English

Thank you for your interest in the Korean edition of ARTEX (artex-ko). This document gathers the scope, policies, and procedures you should know before you start contributing. Before you send a contribution, please read Authorized use and legal responsibility and Localization policy first.

  • To report a bug or suggest a feature → use the issue templates.
  • If you find a translation or localization error → use the "translation/localization error" issue template.
  • If you find a security vulnerability → do not open a public issue; follow the procedure in SECURITY.en.md.
  • Everyone who takes part must follow the Code of Conduct (CODE_OF_CONDUCT.en.md).

ARTEX is an offensive-security tool in which an LLM multi-agent system performs penetration testing autonomously. Contributors are bound by the same scope limits as users.

  • When you verify code, run the tool only against a target you own or have explicit written authorization for, or against a locally isolated environment (for example an intentionally vulnerable target you own, such as OWASP Juice Shop or DVWA launched with Docker).
  • We do not accept code that scans, probes, or exploits real, production, or remote systems outside the authorized scope, nor changes that encourage such use.
  • In the Republic of Korea, intruding into another party's information and communications network without authorization, or causing a disruption to it, violates the Act on Promotion of Information and Communications Network Utilization and Information Protection; and any personal data collected or exposed falls under the Personal Information Protection Act. The full notice is in the README.

Legal responsibility for how the code or documentation you contribute is used rests with the user who runs it. This repository is provided "AS IS."


Localization policy

The reason this repository exists is to preserve the original Autumn-27/ARTEX's judgment performance exactly while changing only the user-facing output to Korean. Translation contributions that depart from this policy can degrade performance, so we do not accept them.

  • Do not translate the agent's internal reasoning prompts (the behavior-instruction body). The behavior benchmarked in the original language (Chinese) must be preserved. This body lives in agent/promptcatalog.go and the DB seed (agent_prompts). Translating it causes drift in the agent's judgment.
  • Only user-facing output is forced into Korean. This covers detection findings (report_finding), fact summaries (record_fact), the final report, and chat responses. The enforcement is a code-fixed tail called langDirective() in agent/prompt.go, appended to the end of each role's system prompt. To change the output language, modify this function.
  • Commands, payloads, code, URLs, and log text are not translated. They are the originals needed for analysis, so they are left as is.
  • The original Chinese is preserved. Documents keep the original in README.zh.md and UI strings keep it in web/messages/zh.json, so that changes in the upstream repository are easy to compare against. Korean translations are filled into web/messages/ko.json.
  • When you translate a new UI string, do not hard-code it; add it as a key in the message files.
  • The output-language enforcement is a prompt nudge, not a hard cap. langDirective() instructs the model to output Korean; it does not force-lock the language. Korean fidelity therefore varies with the model's capability, the role, and the context. Use a capable (frontier-class) model when you verify localization changes. Cheap or small models can revert reports and summaries to the original language (Chinese), so do not judge whether a translation is applied correctly from a cheap model's output alone. The max_tokens pitfall when using OpenAI-family models is covered in the README's "Model selection and output language" section.
  • The procedure for keeping up with upstream changes is in the maintainer document. When the original ARTEX is updated, the runbook for distinguishing preserved assets from translation targets, reflecting them, and checking translation symmetry and drift is in MAINTAINING.en.md.

Development environment

This project consists of a Go backend (with the frontend embedded in a single binary) plus a Next.js frontend.

The design intent of the main features is documented in the design docs under docs/. When you work on the feature that links vulnerabilities to traffic evidence (the report agent's automatic binding, report_finding's traffic_refs, and so on), read the vulnerability multi-traffic-evidence design doc first. The original (Chinese) is preserved as finding-traffic-evidence-zh.md in the same folder.

Required versions

  • Go 1.26 or later (per go.mod)
  • Node.js 22 or later (per the release workflow)
  • Docker and Docker Compose (for local runs and verification)

Backend (Go)

If Go is installed locally, run the following from the repository root.

go build ./...
go vet ./agent/
go test ./agent/

If you do not have Go locally, you can verify the same way with Docker. Keeping the module and build caches in named volumes makes re-runs faster.

docker run --rm -v "$PWD":/src -w /src \
  -v artexko-gomod:/go/pkg/mod -v artexko-gocache:/root/.cache/go-build \
  golang:1.26 sh -c 'go build ./... && go vet ./agent/ && go test ./agent/'

DB integration tests (postgres required)

The go test ./agent/ above quietly skips the DB integration tests that only run when connected to PostgreSQL. Six packages — agent, config, db, evidence, llmrec, server — contain tests that require a real database; if there is no ARTEX_PG_DSN environment variable and no database entry in the config file, those tests are skipped with --- SKIP and the package still ends in ok. As a result, if you fix one of these six packages and verify without a DSN, it can pass locally (ok) while the PR's go-db job fails.

To run these tests locally, bring up PostgreSQL and pass ARTEX_PG_DSN. The example below launches the same postgres:16-alpine as CI on an isolated network, reusing the named volumes from above.

# 1) Bring up an isolated network and an empty postgres (same image and account as CI).
docker network create artexko-db 2>/dev/null || true
docker run -d --name artexko-pg --network artexko-db \
  -e POSTGRES_USER=artex -e POSTGRES_PASSWORD=artex -e POSTGRES_DB=artex \
  postgres:16-alpine
until docker exec artexko-pg pg_isready -U artex -d artex >/dev/null 2>&1; do sleep 1; done

# 2) Pass the DSN to run the DB integration packages (the DSN host is the container name).
#    To run only the package you fixed, replace ./agent/ with config, db, evidence, llmrec, or server.
docker run --rm --network artexko-db -v "$PWD":/src -w /src \
  -v artexko-gomod:/go/pkg/mod -v artexko-gocache:/root/.cache/go-build \
  -e ARTEX_PG_DSN='postgres://artex:artex@artexko-pg:5432/artex?sslmode=disable' \
  golang:1.26 sh -c 'go test ./agent/ -count=1'

# 3) Clean up.
docker rm -f artexko-pg && docker network rm artexko-db

CI's go-db job isolates each of these six packages with its own postgres and forces them to run before merge (.github/workflows/ci.yml). If you changed a DB integration package, we recommend verifying that package directly with the method above before you open the PR.

Frontend (web)

cd web
npm ci
npm run dev          # dev server
npm run build        # production build
npm run build:static # static-export build (merge gate; includes TypeScript type checking)
npm run check        # Biome lint/format check (informational; not a merge gate yet, due to pre-existing debt)
npm run check:fix    # auto-fix

Formatting and linting before commit are managed with Biome. lint-staged automatically runs biome check --write on staged files.

Full run (Docker Compose)

cp .env.example .env     # set POSTGRES_PASSWORD
docker compose up -d     # start artex + postgres → http://localhost:8787

Contribution process

  1. Open an issue first. For large changes it is better to align on direction via an issue before you start. For small fixes (typos, links, obvious bugs) you can send a PR directly.
  2. Fork the repository and create a topic branch. Prefix the branch name with the nature of the change, as in feat/..., fix/..., docs/..., i18n/....
  3. Write the change and run the relevant verification yourself. For a Go change, make the build/vet/test above pass. For a web change, make npm run build:static pass (it also performs the merge gate and the TypeScript type checking). npm run check (Biome) still has pre-existing lint debt inherited from upstream and is not a merge gate yet — web.yml runs it only as an informational step — so you do not need to make all of it pass. Instead, just confirm that your change does not add new errors (when you commit, lint-staged automatically applies biome check --write to the files you staged). If you changed documentation (.md), run python3 -I scripts/check-doc-links.py to confirm that in-repo link/image references and document anchor (#heading) links are not broken. Anchors are built from headings into slugs with the same rule as GitHub and matched, so if you change a heading's text without also fixing the anchor links that pointed to it, it is caught here (CI's docs workflow enforces the same check as a merge gate). This check is also wired as the docs hook in the repository root's .pre-commit-config.yaml, so if you run pre-commit install it runs automatically on every commit (it uses only the Python standard library and no network, so it finishes without Docker).
  4. Open a PR. Follow the PR template for the title and description, and write what you changed, why, and how you verified it. If you changed the UI, attach screenshots.
  5. For a user-facing change (feature, localization, documentation, detection rule, and so on), add one line to the [Unreleased] section of the changelog (CHANGELOG.en.md). Internal refactoring or test-only changes may be omitted.

Commit messages

Follow the convention of the existing commit history. The format is type(scope): description, and the description is written in Korean.

  • type: feat · fix · docs · chore · refactor · test · i18n, and so on
  • scope: the changed area (agent · web · server, and so on); optional

Examples.

feat(agent): 사용자 노출 출력을 한국어로 강제 (langDirective)
docs: 한국어 README 작성, 원본은 README.zh.md 로 보존
i18n(web): 대시보드 네비게이션 라벨 한국어 번역

Contributing detection rules and detection tests

This repository also keeps, in detections/, rules for defending against and detecting autonomous AI attacks like ARTEX. It consists of deployable Sigma rules (detections/sigma/), network Suricata rules (detections/suricata/), a MITRE ATT&CK coverage layer (detections/attack/), and tests that reproducibly prove these rules actually fire (detections/tests/). When you add or change a detection rule, please honor the contract below. Seven test suites mechanically enforce much of this contract, so if you change only a rule and do not update the tests/layer, the tests fail.

  • Ground every indicator in an observable fact. The strings, User-Agents, and behavioral thresholds a rule uses must be ones actually found in this repository's source, and must not be inferred. State the source file that is the basis for the rule (for example, the artex-enrich/1.0 indicator is confirmed in enrich/enrich.go). The indicator-match tests (detections/tests/indicators/) check that each indicator is still present in both the upstream source and the rule, so if an upstream resync changes a source string, the test fails unless you fix the rule along with it. If you change the machine-readable indicator list (detections/indicators/artex_indicators.csv), also update the MISP event that carries those same indicators (detections/indicators/artex_indicators.misp.json). The MISP export test (detections/tests/misp/) enforces that the two files match row by row and that the event is a valid MISP document loadable by pymisp.
  • State limitations honestly. Write what a rule cannot catch and its false-positive potential in the Sigma rule's description and in the Suricata rule's comments. If something is a general hunting lead (for example, a destructive command) rather than an ARTEX-specific signature, say so, so that a single hit does not get used to conclude the attacker is ARTEX.
  • Pass static validation. A Sigma rule must pass the SigmaHQ validator criteria with zero issues (sigma check --validation-config detections/tests/sigma_lint/validators.yml). Plain sigma check runs only pySigma's core validators, so SigmaHQ conventions such as title casing, field/logsource classification, and reference links are filtered only by this config. The four exceptions are SigmaHQ monorepo conventions that do not fit a standalone rule set, and their rationale is recorded in detections/tests/sigma_lint/validators.yml. A Suricata rule must load cleanly with suricata -T.
  • Ship a reproducible test with it. Prove that the rule fires (or that its structure is valid) with a test under detections/tests/. Generate the input deterministically each time rather than committing binaries to the repository; assert properties that are independent of the engine version (firing exists, no false positives) exactly; and for figures that fluctuate with the version, assert a lower bound and record the baseline separately. If you add or change a Sigma correlation rule, the backend portability test (detections/tests/sigma_backends/) checks that the rule converts across multiple backends, so keep it consistent with the backend-support description in detections/README.md.
  • Update the ATT&CK layer with it. If you add or change an attack.* tag on a rule, update the techniques and scores in detections/attack/artex_navigator_layer.json to match. The consistency test enforces a bidirectional rule↔layer match, so it fails if there is a rule tag missing from the layer or a layer technique missing from the rules.
  • Do not include anything that reads as attack guidance. The detection material in this repository maintains a defense/detection posture only. We do not accept write-ups that aid an attack, such as how to carry out an exploit or techniques for evading detection.

The eight test suites run as-is with only Docker, and do not commit their artifacts to the repository. Each script exits with a non-zero code if any single assertion fails, so it can be dropped straight into CI or a pre-commit hook.

detections/tests/sigma/run.sh           # Sigma: sigma check + backend conversion + indicator preservation
detections/tests/sigma_match/run.sh     # Sigma: atomic rules fire on malicious sample events, stay quiet on benign
detections/tests/sigma_lint/run.sh      # Sigma: full SigmaHQ-convention validators + documented criteria
detections/tests/sigma_backends/run.sh  # Sigma portability: does a correlation rule convert across backends
detections/tests/suricata/run.sh        # Suricata: synthesize pcap → suricata -r → assert alert counts
detections/tests/attack/run.sh          # ATT&CK: bidirectional layer ↔ rule consistency
detections/tests/indicators/run.sh      # Indicators: rule's pinned indicators ↔ upstream source, both ways
detections/tests/misp/run.sh            # MISP: indicator CSV ↔ MISP event sync + pymisp validity

To run all eight at once, use detections/tests/run-all.sh. It runs the eight sequentially in the same order as CI, runs the rest to the end even if an earlier suite fails, then prints a per-suite PASS/FAIL summary, and exits with a non-zero code if any one fails. An example of wiring this runner directly as a pre-commit hook is in the repository root's .pre-commit-config.yaml. If you install it with pip install pre-commit && pre-commit install, the runner runs only on commits that change detection rules or the upstream source those rules pin (the same scope as CI), catching rule/test mismatches before push. The same config file also includes the docs hook that checks in-repo link/image/anchor references (the check-doc-links.py from step 3 of the contribution flow above).

These eight tests are run by the repository CI (.github/workflows/detections.yml) on every push/PR that changes anything under detections/. The indicator-match test also runs when the upstream source files those indicators point to (enrich/, selfupdate/, guard/, db/, cmd/artex/main.go) change, catching the case where an upstream resync changes a User-Agent, marker, or default port and silently makes a rule stale. So a change that updates only a rule without updating the tests/layer, a rule that breaks a SigmaHQ convention, or a rule that is inconsistent with the source shows up red in CI before merge.

The rule index and each rule's basis and limitations are in detections/README.md, and the tests' assertions and how to run them are in detections/tests/README.md.


License

This project is distributed under the GNU Affero General Public License v3.0 (AGPL-3.0). By submitting a contribution, you are taken to agree that your contribution is also released under AGPL-3.0. In particular, if you modify this project and provide it to users over a network (for example, as an online service), you must disclose the complete corresponding source code to those users. The full terms are in the LICENSE file.