Content Moderation
Overview
Arweave is a network designed for permanent storage of data. It is a practical impossibility for data to be wholly removed from the network once it has been uploaded.
The AR.IO Network has adopted Arweave's voluntary content moderation model, whereby every participant of the network has the autonomy to decide which content they want to (or can legally) store, serve, and see. Each gateway operating on the network has the right and ability to blocklist any content, ArNS name, or address that is deemed in violation of its content policies or is non-compliant with local regulations.
Gateway operators may set content to be blocked by their gateway by submitting a PUT
request to their gateway defining the content to be blocked. This requires that the ADMIN_API_KEY
environmental variable to be set in order to authenticate the moderation request.
The simplest method for submitting moderation requests to a gateway is to use curl
in a terminal.
Quick Start
Set Up Admin API Key
Configure your admin API key in your .env
file:
# Set a secure admin API key
ADMIN_API_KEY=your_secure_admin_key_here
Security
Choose a strong, unique admin API key. This key provides administrative access to your gateway and should be kept secure.
Test API Access
Verify your admin API key is working:
# Test admin endpoint access
curl -H "Authorization: Bearer your_secure_admin_key_here" \
http://localhost:3000/ar-io/admin/debug
Block Your First Content
Block a specific transaction ID:
curl -X 'PUT' \
'http://localhost:3000/ar-io/admin/block-data' \
-H 'accept: */*' \
-H 'Authorization: Bearer your_secure_admin_key_here' \
-H 'Content-Type: application/json' \
-d '{
"id": "3lyxgbgEvqNSvJrTX2J7CfRychUD5KClFhhVLyTPNCQ",
"notes": "Content violates our policies",
"source": "Manual Review"
}'
Authentication
Moderation requests must contain the gateway's ADMIN_API_KEY
in the request Header, as Authorization: Bearer
.
For example, if a gateway's ADMIN_API_KEY
is set to secret
, any request must contain Authorization: Bearer secret
in the Header.
Block Data
Specific data items can be blocked by a gateway operator by submitting a PUT
request containing a json object with three keys:
- id: The Arweave transaction Id of the data item to be blocked.
- notes: Any note the gateway operator wants to leave him/herself as to the reason the content is blocked.
- source: A note as to where the content was identified as requiring moderation. i.e. a public block list.
Requests to block data must be submitted to the gateway's /ar-io/admin/block-data
endpoint.
curl -X 'PUT' \
'http://localhost:3000/ar-io/admin/block-data' \
-H 'accept: */*' \
-H 'Authorization: Bearer secret' \
-H 'Content-Type: application/json' \
-d '{
"id": "3lyxgbgEvqNSvJrTX2J7CfRychUD5KClFhhVLyTPNCQ",
"notes": "This content is offensive",
"source": "Public Block list"
}'
Unblock Data
At this time, blocked data items can only be unblocked by manually deleting the corresponding row from the data/sqlite/moderation.db
database.
The Arweave transaction Id of the blocked data item is stored in the database as raw bytes, which sqlite3 accepts as a BLOB (Binary Large OBject), and so cannot be accessed easily using the original transaction Id, which is a base64url.
Sqlite3 is able to interact with a hexadecimal representation of the BLOB, by using a BLOB literal. To do so, wrap a hexadecimal representation of the Arweave transaction Id in single quotes, and prepend an X
i.e. X'de5cb181b804bea352bc9ad35f627b09f472721503e4a0a51618552f24cf3424'
.
Where possible, consider using the notes
or source
values to identify rows for deletion rather than the id
.
sqlite3 data/sqlite/moderation.db "DELETE FROM blocked_ids WHERE id=X'de5cb181b804bea352bc9ad35f627b09f472721503e4a0a51618552f24cf3424';"
# Note that the id in this command is a BLOB literal using the hexadecimal representation of the Arweave transaction Id, not the transaction Id in its normal base64url format
sqlite3 data/sqlite/moderation.db "DELETE FROM blocked_ids WHERE block_source_id = (SELECT id FROM block_sources WHERE name='Public Block List');"
# This command uses a subquery to look up the id in block_sources where name='Public Block List'
# This command will unblock ALL data items marked with this source value
Block ArNS Name
ArNS names can be blocked so that a gateway will refuse to serve their associated content even if the name holder updates the Arweave transaction Id that the name points at.
This is done via an authenticated PUT
request to the endpoint /ar-io/admin/block-name
containing a json object with three keys:
- name: The ArNS name to be blocked.
- notes: Any note the gateway operator wants to leave him/herself as to the reason the content is blocked.
- source: A note as to where the content was identified as requiring moderation. i.e. a public block list.
curl -X 'PUT' \
'http://localhost:3000/ar-io/admin/block-name' \
-H 'accept: */*' \
-H 'Authorization: Bearer secret' \
-H 'Content-Type: application/json' \
-d '{
"name": "i-bought-a-potato",
"notes": "Potatoes are offensive",
"source": "Public Block list"
}'
Undernames
For moderation purposes, each undername of an ArNS name is treated as a separate name and must be moderated separately.
Unblock ArNS Name
Gateway operators can unblock ArNS names that were previously blocked.
This is done via an authenticated PUT
request to the endpoint /ar-io/admin/unblock-name
containing a json object with a single key:
- name: The ArNS name to be unblocked
curl -X 'PUT' \
'http://localhost:3000/ar-io/admin/unblock-name' \
-H 'accept: */*' \
-H 'Authorization: Bearer secret' \
-H 'Content-Type: application/json' \
-d '{
"name": "i-bought-a-potato",
}'
How is this guide?