Security and privacy
This page describes what Pinfolio actually protects, how it protects it, and what it does not protect. It is written so you can decide whether to put your clients' work into it — not to impress you.
Protection of the designs rests on one thing: the project password. Everything else (separation between agencies, the private image storage, request limits) supports that password. The level of protection matches a tool for collecting design feedback, not a system for trade secrets.
How a client gets to the designs
The client receives a link to the project's review page — an address on your agency's host in the form /review/project-name. They then go through two steps:
- The project password. Every project has its own password, which you set when you create it. It is stored hashed, so it cannot be read out of the database; alongside it an encrypted readable copy is kept, so the administration can show you the password again when the client needs it resent.
- A name. The client types who they are (at most 100 characters). Their comments and any approval are signed with that name. Under the field is one sentence telling them the name will be seen by the site owner and by other people with access to the project. They can change it later with Change name in the review page's header; the new name applies to what they write from then on, and earlier comments keep the name they were written under.
The client creates no account and goes through no registration. The password and the name are everything they need.
What that proves and what it does not
The project password proves one thing only: that whoever typed it got it from someone. The name proves nothing — it is text anyone can write into a field.
The anonymous browser identifier (see below) is not a sign-in either. It binds the authorship of comments and approvals to one browser, nothing more: it decides on which comments the client sees the pencil and the bin, and who may withdraw an approval. Whoever opens the review page in another browser, in a private window or after clearing cookies is a new visitor to Pinfolio. An approval given by an agency member in the preview is tied to their account, so a client with the same name cannot withdraw it.
Three things worth telling a client up front
- Everyone who passes the password sees every comment and every author name. This is not a shared document for one person: a project is one shared room. If you let two parties into one project, they will see each other's feedback.
- The "Mine only" switch on the review page only changes what is drawn on your screen at that moment. The browser has every thread loaded anyway — it is not protection, it is a filter for readability.
- Anyone who forwards the link along with the password lets anyone else in. The only remedy is to change the project password.
Scope and lifetime of a client's access
- Access is per project. Passing the password for project A gives the client nothing on project B — the second project asks for its password again, even with both pages open in the same browser.
- Changing a project's password signs every client of that project out at once. Confirming the Change password action on the project's edit page sets the new password, and every session already open stops being valid; whoever is in there drops back to the password form. This is the right move when a link has leaked or when somebody should lose access.
- Renaming the project's slug signs nobody out. A client's session belongs to the project, not to its address, and the old addresses forward to the new one.
- A session expires through inactivity. The default is 120 minutes since the last action; your installation may have it set differently — ask the operator. The client then enters the password again — their comments stay, only the access is renewed.
- The session holds the verification, a name and an anonymous identifier: that the password was verified, the name the client typed, and an anonymous browser identifier. The browser also keeps the same identifier in a
review_visitorcookie valid for one year, so that a client whose session expired does not lose authorship of their comments. It is random, carries no personal data, cannot be read by scripts on the page and is sent only to review pages. - You, signed in as a team member, need no password. You open your own projects straight from the administration and the review page marks it with an "Admin preview" banner. That works only on your own agency's host.
The session cookie is not available to JavaScript and is sent only to this address. The installation can send security headers with every page — including one that tells browsers to use only HTTPS for this address — but they are switched off unless the operator turns them on. Ask the operator whether they are on.
Who reaches the administration
- Only invited people. There is no registration; a new member comes into being only by accepting an invitation sent by an owner. The invitation link is valid for 7 days, can be resent and revoked, and can be used once.
- Only on their own agency's host. The administration at
/adminopens only for a user who belongs to the agency that address belongs to. A member of one agency signing in on another agency's host is refused (403). - The exception is a super admin, the operator. They reach the administration on any host as well as on the platform host and see every agency. It is the role for whoever runs the installation.
- The sign-in form allows 5 attempts a minute. A forgotten password is handled by a reset link sent by mail.
- Roles inside an agency (owner, member) are described in Team and roles. The last owner can be neither removed nor demoted, so an agency is never left without an owner.
Separation between agencies
One installation can run several agencies, each on its own host. The boundary between them is a security boundary and three rules hold it:
- The address the request arrived on decides the agency, freshly for every request, before it is even decided which page will be shown. A verified subdomain or custom domain of a live agency means that agency.
- An address that belongs to no verified agency answers 404. Nothing is guessed and nothing is offered: an unknown host sees nobody's data.
- An archived agency stops answering entirely. Its hosts stop being recognised, so they answer the same 404 as an unknown address — review pages, portfolios and the administration are unreachable from the internet, although the data stays in the database.
The whole boundary rests on one operating condition
The application takes the address from the request. By default it believes whatever the proxy in front of it says the address was — including a header anyone can send. The installation can be limited to believing only its own proxy; if it is not, the separation between agencies holds only as long as the application is reachable exclusively through that proxy. Ask the operator whether the installation trusts only its own proxy, or is reachable only through it.
On top of that, every database query is confined to the agency currently chosen, and when none is chosen, a query for projects, screens and comments returns nothing — nothing rather than everything.
The same rule holds the AI endpoint: the token is compared against the token of the agency the address belongs to. One agency's token opens nothing at another, and an agency without a token has no endpoint at all (see AI access (MCP)).
The design files
- They are never in a public directory. The image storage is private; the web server has no path to it and no guessed address reaches it.
- Every agency has its own directory, and an uploaded file is accepted only when it lands in the directory of the agency uploading it.
- An image is served only by an address behind the full access check. Whoever has not passed the password and the name gets no image; a version that does not belong to the project of that session answers 404. The response may be stored only in the client's own browser, never in a shared cache.
- File names are generated, so nothing can be read or guessed from them.
- Uploads are limited by type and by size:
| What you upload | Accepted formats | Maximum |
|---|---|---|
| A screen (design) | PNG, JPEG, WebP | 10 MB |
| Agency logo | PNG, JPEG, WebP, SVG | 2 MB |
| Favicon | PNG, SVG, ICO | 512 kB |
| Profile picture | image | 2 MB |
Portfolio images are the exception: they are served to anyone without a password, because that is their point. See Portfolio.
URL captures
Screens from a URL are captured outside Pinfolio — by an external website-screenshot service (ScreenshotOne). For every capture Pinfolio sends it:
- the page address,
- for a password-protected staging site also the user name and password (HTTP basic auth), because without them the service could not reach the page.
The service opens the page in its own browser, just as anyone else would, and returns an image. So do not capture a page nobody outside your team should see — and for staging, use credentials that are good for nothing else.
How Pinfolio treats the credentials:
- They are stored encrypted, and only when you fill in the user.
- The password is only ever written, never read back. The password field in Capture source is always empty; the panel shows at most the user name. The password does not go into an agency export either.
- The password stays with its site. When you change the address in Capture source to another site (a different domain, scheme or port), the stored password is not used for it and you have to enter it again — otherwise it could be sent to someone else's address and read there.
- They can be removed at any time with the Remove the stored credentials checkbox in Capture source, or by clearing the user name. Deleting the screen removes them too.
Whether capture is enabled is up to the operator. When it is not, Pinfolio sends no address anywhere.
What is rate-limited
Limits are per minute, and for visitors who are not signed in, per IP address.
| What | Limit |
|---|---|
| Submitting a project password | 10 attempts |
| Submitting the invitation form | 10 |
| A new comment or reply | 20 |
| Editing or deleting a comment | 20 |
| Approving and withdrawing an approval | 20 |
| Moving a pin | 60 |
| Marking a thread resolved | 60 |
| The page asking for new comments | 60 |
| Signing in to the administration | 5 attempts |
Not limited: opening the review page and a screen, the name form, downloading images, the public portfolio, and the AI endpoint. For the portfolio and the images that is deliberate (images load by the dozen); for the AI endpoint the token is the only protection. Whether anything else limits it is something the operator knows.
What search engines are told
- Every client-facing page — the password form, the name form, the screens, the closed-project page, an invitation and an agency's landing page — sends
noindex, nofollow. - Pinfolio's presentation page on the installation's main address sends no such instruction, and search engines may index it. It carries nothing from any agency.
- It is an instruction to search engines and nothing more: what protects the content is the project password, not a request to a search engine.
- Portfolios are a deliberate exception. A personal portfolio at
/@{username}and the projects on it, and — once the owner switches it on — the agency portfolio, meaning the agency host's homepage and the/work/…pages, ask forindex, followinstead: they are meant to be found. Exactly what that publishes (the approved versions of the chosen projects' screens and the versions before them — or every version, where Show unapproved work is on — without comments) is described in Portfolio. Each project in a portfolio can be given a public title and a public slug, so that neither the client's name nor the review page's slug appears on the page. An agency owner can switch every personal portfolio of the agency off at once with Allow public portfolios on the Branding page; the agency portfolio is switched off separately with Agency portfolio is public on the Agency portfolio page. While it is off, the homepage is the sign-in card withnoindex, nofollow, and the/work/…addresses answer 404.
Privacy in practical terms
What personal data exists at all
| Whose | What is stored |
|---|---|
| A client | the name they typed, the text of their comments, when they were written, the name on an approval, and an anonymous browser identifier on comments and approvals |
| A team member | name, e-mail, hashed password, role; optionally a username, picture, headline, text about themselves and links |
| An invited person | e-mail address, who invited them, and how long the invitation is valid |
| The agency | the address notifications go to and the sender name on mail |
No IP address is stored with a comment, and nothing about the client's device. IP addresses can appear only in the server's ordinary operational logs. An approval given by an agency member in the preview carries no browser identifier.
Where the data ends up
- In the installation's database. The name the client typed also sits in the session store for as long as their session lasts.
- In the client's browser. The
review_visitorcookie with the anonymous identifier stays there for one year. - In notification mail. The new-comment notification contains the author's name and the text of the comment and goes to a single address — the one the agency has set for notifications. A reply to such a mail goes to the same address. Details in E-mail notifications.
- In an agency export, which the operator can run. It contains the agency, its domains, users, projects, screens, versions and comments, plus the files, and for a screen from a URL its address. Passwords (neither hashed nor readable), staging credentials and the AI token are not in it.
- With the website-screenshot service, if you capture from a URL. It receives the page address and, where set, the staging user name and password — see URL captures.
- With an analytics provider, if that is switched on. Analytics load on the review pages only when the operator has configured them and the agency is on a plan with that feature and has entered a site id.
- With Google when fonts load. The client-facing pages take their fonts from Google Fonts, so a client's browser contacts Google when the page opens. If that is a problem for you, raise it with the operator.
How long it stays
For as long as nobody deletes it. There is no automatic retention period and no background clean-up: a comment from last year's project will still be there in five years if the project is. If that is not enough for you, agree on an interval for deleting archived projects and keep to it.
How to delete it
| What you delete | What goes with it |
|---|---|
| A comment on the review page | that comment; at the start of a thread, every reply in it as well |
| A screen version | every comment on that version, and its image files |
| A screen | all of its versions, their comments and images |
| A project | all screens, versions, comments, approvals and images |
| A user | their account and profile; their comments stay, because only the name is kept with them, as text |
| An agency | the agency's projects, users, invitations, domains and all of its files (the operator does this) |
Comments are not deleted in the administration
In the administration comments are read-only; they can be marked resolved in bulk, but not deleted there. You delete one particular comment on the review page: signed in as an agency member, in the preview, with the bin icon on a comment or reply, on any version of a screen, older ones included. A client may delete only their own comment on the newest version, and only shortly after writing it. On the day somebody asks you to erase one name, go through the older versions as well — copies of carried-over threads stay there.
Who the data controller is
The controller is the agency: it decides who is let into a project, what it asks of a client and when it deletes it. Whoever runs the installation (with self-hosting, often the same company; otherwise the operator) is the processor — they hold the database and the files and carry out deletions and exports. Where those are two different parties, a data-processing agreement belongs between them; Pinfolio replaces none of that.
What this is not
- It is not a signed-link system. A project link is neither secret nor self-expiring; the password is what is secret.
- It is not end-to-end encrypted. Images and comments sit on the server in readable form, and whoever has access to the server or the database reads them.
- It is not per-client access control. A project has one password for everybody and no client accounts. There is no way to arrange for one person to see only their own threads.
- It is not an audit trail. A comment tells you a name and a time, not who really wrote it.
When a project is genuinely confidential:
- Create a separate project for each party instead of one shared one. Separate projects are the only boundary Pinfolio knows.
- Give the project a strong password and send it by a different route than the link itself.
- Change the password whenever someone should lose access — that signs everyone out at once.
- Archive the project when it is over. Clients then see only the "project is closed" page (HTTP 410), no matter who holds the link or the password.
- Once you no longer need the history either, have the project deleted — that takes the images off the disk as well.
What to check with the operator
These things are not arranged in the administration — whoever runs the installation arranges them. They are worth asking about before you hand over your clients' work:
- whether the security headers are switched on, including the one that tells browsers to use only HTTPS for the address;
- whether the installation trusts only its own proxy, or is reachable only through it;
- how the installation's secrets are protected — the readable copies of project passwords and the AI tokens are secured together for every agency, so a leak would affect all agencies at once;
- whether and how the data is backed up, and how long backups are kept;
- whether operational logs with IP addresses are kept, and for how long;
- whether anything limits the number of requests to the AI endpoint;
- whether the client-facing pages load fonts from a third party;
- who carries out the deletion of an agency and exports, and how.
Where to next
- Team and roles — who reaches the administration and what they may do there.
- Guide for clients — what a client sees and can do on the review page.
- Portfolio — what is shown publicly and how to switch it off.
- Troubleshooting — when a client cannot get in.
- Documentation home