Skip to content
Merged
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
3 changes: 3 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
18 changes: 16 additions & 2 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -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}
```
Expand All @@ -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
Expand Down
43 changes: 38 additions & 5 deletions docs/plugins.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ Plugins are enabled or disabled under plugins.<name>.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 <text>` creates a paste through an Opengist-compatible server. If the
Expand All @@ -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

Expand All @@ -85,14 +94,18 @@ library:
~~~text
!hash sha256 hello
!md5 hello
!sha1 hello
!sha256 hello
!sha512 hello
!b64encode hello world
!b64decode aGVsbG8=
!urlencode hello world
!urldecode hello+world
~~~

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

Expand All @@ -101,27 +114,47 @@ 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

`!audit <go|npm|pip> <package> [version]` queries OSV for known package
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

`!docker nginx` looks up an official Docker Hub image, while
`!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/_/<image>`; an image containing one slash is treated as a
user or organization image and links to `hub.docker.com/r/<user>/<image>`.

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
Expand Down
11 changes: 10 additions & 1 deletion docs/security.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down