From aed33f36af87b7134f1d56acea8fb7938f2aa76f Mon Sep 17 00:00:00 2001 From: AK Date: Sat, 8 Aug 2026 04:24:54 -0700 Subject: [PATCH] docs: complete plugin and security documentation --- .env.example | 3 +++ README.md | 7 +++++-- config.yaml | 2 +- docs/configuration.md | 18 ++++++++++++++++-- docs/plugins.md | 43 ++++++++++++++++++++++++++++++++++++++----- docs/security.md | 11 ++++++++++- 6 files changed, 73 insertions(+), 11 deletions(-) diff --git a/.env.example b/.env.example index d0b95b1..ee701d3 100644 --- a/.env.example +++ b/.env.example @@ -13,6 +13,9 @@ BOT_NEWS_API_KEY=replace-with-your-newsapi-key BOT_YOUTUBE_API_KEY=replace-with-your-youtube-data-api-key BOT_LASTFM_API_KEY=replace-with-your-lastfm-api-key BOT_GITHUB_TOKEN=replace-with-an-optional-github-token +# Optional Opengist paste integration. Keep the token out of config.yaml. +BOT_PASTE_BASE_URL=https://paste.example.net +BOT_PASTE_TOKEN=replace-with-your-opengist-token # Optional source-grounded question rewriting. Leave provider as none for # keyless Wikipedia/DuckDuckGo answers. BOT_ASK_PROVIDER=none diff --git a/README.md b/README.md index 7646d1c..f377a9c 100644 --- a/README.md +++ b/README.md @@ -9,8 +9,9 @@ GoBot is an extensible Go IRC bot for long-running use on one or more IRC networks. It supports TLS/SASL authentication, multiple networks and channels, persistent plugin data, rate-limited responses, games, reminders, source-grounded question answers, URL titles, and Prometheus metrics. -It also includes keyless CVE and IP/ASN lookups, local acronym expansion, and -a persistent word-scramble game. +It also includes keyless CVE, package, OSV, Docker Hub, and IP/ASN lookups, +Opengist pastes, local crypto/encoding and port utilities, local acronym +expansion, and a persistent word-scramble game. The repository contains example connection settings so you can see the configuration shape. Replace them with the networks, channels, identity, and @@ -54,6 +55,7 @@ Requirements: 1. Review `config.yaml` and add your networks and channels. 2. Copy `.env.example` to `.env` and add secrets such as SASL or API keys. + When enabling paste, also set `BOT_PASTE_BASE_URL` and `BOT_PASTE_TOKEN`. 3. Build the binary with `make build` or `./scripts/build.sh`. 4. For a direct launch, export the `.env` values before starting the binary: `set -a; . ./.env; set +a; ./bin/irc-bot`. GoBot reads environment variables; @@ -97,6 +99,7 @@ data/scramble.txt local word-scramble catalog data/weapons.txt local high-level firearm and weapons-name catalog data/sports.txt local sports suggestion list data/cars.txt local car make/model suggestion list +data/ports.txt local IANA well-known port/service catalog storage/ BoltDB wrapper used by stateful plugins quotes/ built-in quote and response files grafana/ importable Prometheus dashboard and preview diff --git a/config.yaml b/config.yaml index 990df58..7e540fc 100644 --- a/config.yaml +++ b/config.yaml @@ -148,7 +148,7 @@ plugins: max_input_length: 4096 crypto: {enabled: true} pkg: {enabled: true, timeout_seconds: 8, max_length: 300} - port: {enabled: true, data_file: "data/ports.txt", max_length: 350} + port: {enabled: true, data_file: "data/ports.txt"} audit: {enabled: true, timeout_seconds: 8, max_length: 400, max_vulns_shown: 3} docker: {enabled: true, timeout_seconds: 8, max_length: 300} # Public GitHub lookups; token is optional and should be supplied out-of-band. diff --git a/docs/configuration.md b/docs/configuration.md index 853b00a..a9cc657 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -141,10 +141,16 @@ plugins: # 65% is a balanced casual default; use 100% for deterministic testing. pool: {enabled: true, game_timeout_minutes: 30, turn_timeout_seconds: 120, shot_success_percent: 65} horoscope: {enabled: true, max_summary_length: 360} - paste: {enabled: true, provider: opengist, base_url: "", default_visibility: unlisted, max_input_length: 4096} + paste: + enabled: true + provider: opengist + base_url: "" # BOT_PASTE_BASE_URL overrides this value + token: "" # use BOT_PASTE_TOKEN; this field is intentionally ignored + default_visibility: unlisted + max_input_length: 4096 crypto: {enabled: true} pkg: {enabled: true, timeout_seconds: 8, max_length: 300} - port: {enabled: true, data_file: "data/ports.txt", max_length: 350} + port: {enabled: true, data_file: "data/ports.txt"} audit: {enabled: true, timeout_seconds: 8, max_length: 400, max_vulns_shown: 3} docker: {enabled: true, timeout_seconds: 8, max_length: 300} ``` @@ -167,6 +173,14 @@ lookups. Their output limits prevent a slow or unusually large response from holding up the bot or flooding IRC. Disable any of them with `enabled: false` if they are not wanted. +The paste plugin uses `BOT_PASTE_BASE_URL` and `BOT_PASTE_TOKEN`; the token is +not loaded from `config.yaml`. `default_visibility` accepts `public`, +`unlisted`, or `private`, and `max_input_length` bounds inline text and fetched +URL content. Package, audit, and Docker lookups use the configured +`timeout_seconds` and `max_length` values. The port plugin reads its local +catalog from `data/ports.txt` and has a fixed bounded response; it has no +`max_length` setting. + `daily` provides `!daily` in channels. Each authenticated account can claim once per UTC calendar day, regardless of channel or network; users without an account tag are limited by network and nickname. Different users can each diff --git a/docs/plugins.md b/docs/plugins.md index 8da1a27..124fbdf 100644 --- a/docs/plugins.md +++ b/docs/plugins.md @@ -57,6 +57,10 @@ Plugins are enabled or disabled under plugins..enabled in config.yaml. Most command responses are rate-limited. See [Configuration](configuration.md#rate-limits-and-join-warmup). +Every command in the six plugins below emits exactly one bounded IRC line per +invocation. Third-party text is sanitized, and summaries use truncation or a +`+ N more` suffix rather than sending additional lines. + ## Paste `!paste ` creates a paste through an Opengist-compatible server. If the @@ -75,7 +79,12 @@ plugins: Set `BOT_PASTE_BASE_URL` and `BOT_PASTE_TOKEN` in `.env` or the service environment. The token is never read from `config.yaml`; oversized input is -truncated and reported in the single response line. +truncated and reported in the single response line. URL fetching is an +outbound request made from the bot host, follows HTTP redirects, and can reach +any address permitted by that host's network. Do not enable URL pasting for +untrusted users without restricting egress at the host or network firewall; +disable the plugin with `plugins.paste.enabled: false` if that boundary cannot +be enforced. ## Crypto and encoding @@ -85,6 +94,9 @@ library: ~~~text !hash sha256 hello !md5 hello +!sha1 hello +!sha256 hello +!sha512 hello !b64encode hello world !b64decode aGVsbG8= !urlencode hello world @@ -92,7 +104,8 @@ library: ~~~ Input is capped at 512 characters and results are sanitized before being sent -to IRC. These commands make no network requests. +to IRC. Invalid input returns one error line. These commands make no network +requests. ## Package metadata @@ -101,11 +114,24 @@ optional version for a specific release. `!package` is an alias. The plugin uses the public Go module proxy, npm registry, and PyPI endpoints, requires no API keys, and bounds both request time and response length. +Examples: + +~~~text +!pkg go github.com/variablenix/GoBot +!pkg npm lodash +!pkg pip requests 2.32.3 +~~~ + +Responses include the registry version, a sanitized description when present, +and the canonical package page. `!package` is the only alias. + ## Ports `!port 443` looks up a port number and `!port ssh` looks up a service name. `!ports` is an alias. The catalog is local and can be maintained in -`data/ports.txt`; it does not make network requests. +`data/ports.txt`; it does not make network requests. The catalog includes every +port from 0 through 1023 plus common higher-numbered services. Output is +bounded to one line and the plugin has no configurable `max_length`. ## Vulnerability audit @@ -113,7 +139,12 @@ API keys, and bounds both request time and response length. vulnerabilities. `!vuln` and `!osv` are aliases. Without a version, GoBot also checks the package's current registry version and reports whether that latest version is affected. Set `max_vulns_shown` to control the number of CVEs shown -in the one-line summary; `BOT` secrets are not required. +in the one-line summary; `timeout_seconds` and `max_length` also apply. No API +key is required. With no version, the request omits the OSV `version` field, +then fetches the latest registry version and evaluates OSV affected ranges. +With a version, it performs an exact OSV query. Severity comes from OSV's +database-specific or severity fields, and fixed versions are shown when OSV +provides them. ## Docker Hub @@ -121,7 +152,9 @@ in the one-line summary; `BOT` secrets are not required. `!docker traefik/traefik` looks up a user or organization image. `!hub` and `!dockerhub` are aliases. The plugin uses Docker Hub's public repository and tag APIs, formats pull counts compactly, and keeps the response to one IRC -line. +line. An image without a slash uses Docker Hub's `library` namespace and links +to `hub.docker.com/_/`; an image containing one slash is treated as a +user or organization image and links to `hub.docker.com/r//`. The full `!help` menu is kept short in channels. If it would exceed one message, GoBot sends the complete menu to the requesting user's PM and posts a diff --git a/docs/security.md b/docs/security.md index 85a1c2b..ba466a6 100644 --- a/docs/security.md +++ b/docs/security.md @@ -32,7 +32,16 @@ dependencies, and deployment configuration maintained. the port to the Prometheus host. - The URL title plugin rejects loopback, private, link-local, multicast, and local host targets to reduce SSRF risk. -- External HTTP lookups use timeouts and bound response sizes. +- External HTTP lookups use timeouts and bound response sizes. Package, audit, + and Docker requests use fixed public provider hosts. +- The paste plugin's URL mode is different: it fetches a user-supplied HTTP or + HTTPS URL from the bot host and follows redirects. Treat it as an outbound + network capability. Only enable it where users are trusted and host/network + egress rules prevent access to loopback, private, link-local, metadata, and + other sensitive services; otherwise disable `plugins.paste.enabled`. +- The paste token is sent only to the configured Opengist base URL and should + use HTTPS. `BOT_PASTE_TOKEN` and `BOT_PASTE_BASE_URL` belong in the service + environment, not in Git. - IRC invitations, command handling, and cooldown warnings are rate-limited. - The Docker image runs as a non-root user. - Protect the BoltDB data file and its containing directory with filesystem