diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/bugreporting/BugReportingSharedModule.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/bugreporting/BugReportingSharedModule.kt
index 638bc4082866a671d4fa8b1222f3da2111faf573..b753f30df1c058f28895e797933d93c78edd28f0 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/bugreporting/BugReportingSharedModule.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/bugreporting/BugReportingSharedModule.kt
@@ -16,6 +16,7 @@ import de.rki.coronawarnapp.bugreporting.censors.submission.PcrQrCodeCensor
 import de.rki.coronawarnapp.bugreporting.censors.submission.RACoronaTestCensor
 import de.rki.coronawarnapp.bugreporting.censors.submission.RatProfileCensor
 import de.rki.coronawarnapp.bugreporting.censors.submission.RatQrCodeCensor
+import de.rki.coronawarnapp.bugreporting.censors.vaccination.CertificateQrCodeCensor
 import de.rki.coronawarnapp.bugreporting.debuglog.internal.DebugLoggerScope
 import de.rki.coronawarnapp.bugreporting.debuglog.internal.DebuggerScope
 import de.rki.coronawarnapp.bugreporting.debuglog.upload.server.LogUploadApiV1
@@ -117,4 +118,8 @@ class BugReportingSharedModule {
     @Provides
     @IntoSet
     fun ratProfileCensor(censor: RatProfileCensor): BugCensor = censor
+
+    @Provides
+    @IntoSet
+    fun certificateQrCodeCensor(censor: CertificateQrCodeCensor): BugCensor = censor
 }
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/bugreporting/censors/vaccination/CertificateQrCodeCensor.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/bugreporting/censors/vaccination/CertificateQrCodeCensor.kt
new file mode 100644
index 0000000000000000000000000000000000000000..b3de1ea4f938ebcb8e7b4f2287702d5a50a4072c
--- /dev/null
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/bugreporting/censors/vaccination/CertificateQrCodeCensor.kt
@@ -0,0 +1,162 @@
+package de.rki.coronawarnapp.bugreporting.censors.vaccination
+
+import dagger.Reusable
+import de.rki.coronawarnapp.bugreporting.censors.BugCensor
+import de.rki.coronawarnapp.bugreporting.censors.BugCensor.Companion.toNewLogLineIfDifferent
+import de.rki.coronawarnapp.bugreporting.debuglog.LogLine
+import de.rki.coronawarnapp.vaccination.core.certificate.VaccinationDGCV1
+import de.rki.coronawarnapp.vaccination.core.qrcode.VaccinationCertificateData
+import java.util.LinkedList
+import javax.inject.Inject
+
+@Reusable
+class CertificateQrCodeCensor @Inject constructor() : BugCensor {
+
+    override suspend fun checkLog(entry: LogLine): LogLine? {
+        var newMessage = entry.message
+
+        synchronized(qrCodeStringsToCensor) { qrCodeStringsToCensor.toList() }.forEach {
+            newMessage = newMessage.replace(
+                it,
+                PLACEHOLDER + it.takeLast(4)
+            )
+        }
+
+        synchronized(certsToCensor) { certsToCensor.toList() }.forEach {
+            it.certificate.apply {
+                newMessage = newMessage.replace(
+                    dob,
+                    "vaccinationCertificate/dob"
+                )
+
+                newMessage = newMessage.replace(
+                    dateOfBirth.toString(),
+                    "vaccinationCertificate/dateOfBirth"
+                )
+
+                newMessage = censorNameData(nameData, newMessage)
+
+                vaccinationDatas.forEach { data ->
+                    newMessage = censorVaccinationData(data, newMessage)
+                }
+            }
+        }
+
+        return entry.toNewLogLineIfDifferent(newMessage)
+    }
+
+    private fun censorVaccinationData(
+        vaccinationData: VaccinationDGCV1.VaccinationData,
+        message: String
+    ): String {
+        var newMessage = message
+
+        newMessage = newMessage.replace(
+            vaccinationData.dt,
+            "vaccinationData/dt"
+        )
+
+        newMessage = newMessage.replace(
+            vaccinationData.marketAuthorizationHolderId,
+            "vaccinationData/marketAuthorizationHolderId"
+        )
+
+        newMessage = newMessage.replace(
+            vaccinationData.medicalProductId,
+            "vaccinationData/medicalProductId"
+        )
+
+        newMessage = newMessage.replace(
+            vaccinationData.targetId,
+            "vaccinationData/targetId"
+        )
+
+        newMessage = newMessage.replace(
+            vaccinationData.certificateIssuer,
+            "vaccinationData/certificateIssuer"
+        )
+
+        newMessage = newMessage.replace(
+            vaccinationData.uniqueCertificateIdentifier,
+            "vaccinationData/uniqueCertificateIdentifier"
+        )
+
+        newMessage = newMessage.replace(
+            vaccinationData.countryOfVaccination,
+            "vaccinationData/countryOfVaccination"
+        )
+
+        newMessage = newMessage.replace(
+            vaccinationData.vaccineId,
+            "vaccinationData/vaccineId"
+        )
+
+        newMessage = newMessage.replace(
+            vaccinationData.vaccinatedAt.toString(),
+            "vaccinationData/vaccinatedAt"
+        )
+
+        return newMessage
+    }
+
+    private fun censorNameData(nameData: VaccinationDGCV1.NameData, message: String): String {
+        var newMessage = message
+
+        nameData.familyName?.let { fName ->
+            newMessage = newMessage.replace(
+                fName,
+                "nameData/familyName"
+            )
+        }
+
+        newMessage = newMessage.replace(
+            nameData.familyNameStandardized,
+            "nameData/familyNameStandardized"
+        )
+
+        nameData.givenName?.let { gName ->
+            newMessage = newMessage.replace(
+                gName,
+                "nameData/givenName"
+            )
+        }
+
+        nameData.givenNameStandardized?.let { gName ->
+            newMessage = newMessage.replace(
+                gName,
+                "nameData/givenNameStandardized"
+            )
+        }
+
+        return newMessage
+    }
+
+    companion object {
+        private val qrCodeStringsToCensor = LinkedList<String>()
+
+        fun addQRCodeStringToCensor(rawString: String) = synchronized(qrCodeStringsToCensor) {
+            qrCodeStringsToCensor.apply {
+                if (contains(rawString)) return@apply
+                addFirst(rawString)
+                // Max certs is at 4, but we may scan invalid qr codes that are not added which will be shown in raw
+                if (size > 8) removeLast()
+            }
+        }
+
+        fun clearQRCodeStringToCensor() = synchronized(qrCodeStringsToCensor) { qrCodeStringsToCensor.clear() }
+
+        private val certsToCensor = LinkedList<VaccinationCertificateData>()
+        fun addCertificateToCensor(cert: VaccinationCertificateData) = synchronized(certsToCensor) {
+            certsToCensor.apply {
+                if (contains(cert)) return@apply
+                addFirst(cert)
+                // max certs we should have is 2, 50% leeway
+                if (size > 4) removeLast()
+            }
+        }
+
+        fun clearCertificateToCensor() = synchronized(certsToCensor) { certsToCensor.clear() }
+
+        private const val PLACEHOLDER = "########-####-####-####-########"
+    }
+}
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/qrcode/CoronaTestQRCodeValidator.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/qrcode/CoronaTestQRCodeValidator.kt
index 55ddd315ae27b7b1fac8c1e446b9b09f58980d7c..7b31a977326e8cf8f72a7b76938766d79e1c1d3f 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/qrcode/CoronaTestQRCodeValidator.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/qrcode/CoronaTestQRCodeValidator.kt
@@ -14,7 +14,7 @@ class CoronaTestQrCodeValidator @Inject constructor(
     fun validate(rawString: String): CoronaTestQRCode {
         return findExtractor(rawString)
             ?.extract(rawString)
-            ?.also { Timber.i("Extracted data from QR code is $it") }
+            ?.also { Timber.i("Extracted data from QR code is %s", it) }
             ?: throw InvalidQRCodeException()
     }
 
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/qrcode/VaccinationQRCodeExtractor.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/qrcode/VaccinationQRCodeExtractor.kt
index b4ab3e75377eb1e08946d52e27f01f3175155e9e..ae3065df399be47ee02e1d6fe5650ad3ea51b2a0 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/qrcode/VaccinationQRCodeExtractor.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/qrcode/VaccinationQRCodeExtractor.kt
@@ -1,5 +1,6 @@
 package de.rki.coronawarnapp.vaccination.core.qrcode
 
+import de.rki.coronawarnapp.bugreporting.censors.vaccination.CertificateQrCodeCensor
 import de.rki.coronawarnapp.coronatest.qrcode.QrCodeExtractor
 import de.rki.coronawarnapp.util.compression.inflate
 import de.rki.coronawarnapp.util.encoding.Base45Decoder
@@ -22,6 +23,8 @@ class VaccinationQRCodeExtractor @Inject constructor(
     override fun canHandle(rawString: String): Boolean = rawString.startsWith(PREFIX)
 
     override fun extract(rawString: String): VaccinationCertificateQRCode {
+        CertificateQrCodeCensor.addQRCodeStringToCensor(rawString)
+
         val parsedData = rawString
             .removePrefix(PREFIX)
             .decodeBase45()
@@ -56,6 +59,8 @@ class VaccinationQRCodeExtractor @Inject constructor(
             header = headerParser.parse(cbor),
             certificate = bodyParser.parse(cbor)
         ).also {
+            CertificateQrCodeCensor.addCertificateToCensor(it)
+        }.also {
             Timber.v("Parsed vaccination certificate for %s", it.certificate.nameData.familyNameStandardized)
         }
     }
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/qrcode/VaccinationQRCodeValidator.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/qrcode/VaccinationQRCodeValidator.kt
index 84f1a745a2b2afbdb95d8396999e784f5bee4113..3e7f603962d7306ea8bde1da607008559c94c7c1 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/qrcode/VaccinationQRCodeValidator.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/qrcode/VaccinationQRCodeValidator.kt
@@ -14,9 +14,11 @@ class VaccinationQRCodeValidator @Inject constructor(
     private val extractors = setOf(vaccinationQRCodeExtractor)
 
     fun validate(rawString: String): VaccinationCertificateQRCode {
+        // If there is more than one "extractor" in the future, check censoring again.
+        // CertificateQrCodeCensor.addQRCodeStringToCensor(rawString)
         return findExtractor(rawString)
             ?.extract(rawString)
-            ?.also { Timber.i("Extracted data from QR code is $it") }
+            ?.also { Timber.i("Extracted data from QR code is %s", it) }
             ?: throw InvalidHealthCertificateException(VC_PREFIX_INVALID)
     }
 
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/repository/storage/VaccinationContainer.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/repository/storage/VaccinationContainer.kt
index c286d3d9b4cbd87dc75dfbc8b556b5c6dfc1355d..b76916194b49ab4bcb1090bedb3cea556db50694 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/repository/storage/VaccinationContainer.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/repository/storage/VaccinationContainer.kt
@@ -32,7 +32,7 @@ data class VaccinationContainer internal constructor(
     constructor() : this("", Instant.EPOCH)
 
     @delegate:Transient
-    private val certificateData: VaccinationCertificateData by lazy {
+    internal val certificateData: VaccinationCertificateData by lazy {
         preParsedData ?: qrCodeExtractor.extract(vaccinationQrCode).parsedData
     }
 
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/repository/storage/VaccinationStorage.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/repository/storage/VaccinationStorage.kt
index ee8d04c714deaf19c73b3d36dde07c43b3c7bd92..1424b943171378f04cc41ee44a398e0705afc95f 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/repository/storage/VaccinationStorage.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/repository/storage/VaccinationStorage.kt
@@ -36,9 +36,9 @@ class VaccinationStorage @Inject constructor(
                     return@mapNotNull null
                 }
                 value as String
-                gson.fromJson<VaccinatedPersonData>(value).also {
-                    Timber.tag(TAG).v("Person loaded: %s", it)
-                    requireNotNull(it.identifier)
+                gson.fromJson<VaccinatedPersonData>(value).also { personData ->
+                    Timber.tag(TAG).v("Person loaded: %s", personData)
+                    requireNotNull(personData.identifier)
                 }
             }
             return persons.toSet()
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/bugreporting/censors/vaccination/CertificateQrCodeCensorTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/bugreporting/censors/vaccination/CertificateQrCodeCensorTest.kt
new file mode 100644
index 0000000000000000000000000000000000000000..e6c2927121c341a2a08c37e043b5953f86340121
--- /dev/null
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/bugreporting/censors/vaccination/CertificateQrCodeCensorTest.kt
@@ -0,0 +1,130 @@
+package de.rki.coronawarnapp.bugreporting.censors.vaccination
+
+import de.rki.coronawarnapp.bugreporting.debuglog.LogLine
+import de.rki.coronawarnapp.vaccination.core.certificate.VaccinationDGCV1
+import de.rki.coronawarnapp.vaccination.core.qrcode.VaccinationCertificateData
+import io.kotest.matchers.shouldBe
+import io.mockk.MockKAnnotations
+import io.mockk.mockk
+import kotlinx.coroutines.test.runBlockingTest
+import org.junit.jupiter.api.AfterEach
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
+
+internal class CertificateQrCodeCensorTest {
+
+    private val testRawString =
+        "HC1:6BFOXN*TS0BI\$ZD.P9UOL97O4-2HH77HRM3DSPTLRR+%3.ZH9M9ESIGUBA KWML/O6HXK 0D+4O5VC9:BPCNYKMXEE1JAA/CZIK0JK1WL260X638J3-E3GG396B-43FZT-43:S0X37*ZV+FNI6HXY0ZSVILVQJF//05MVZJ5V.499TXY9KK9+OC+G9QJPNF67J6QW67KQY466PPM4MLJE+.PDB9L6Q2+PFQ5DB96PP5/P-59A%N+892 7J235II3NJ7PK7SLQMIJSBHVA7UJQWT.+S+ND%%M%331BH.IA.C8KRDL4O54O4IGUJKJGI0JAXD15IAXMFU*GSHGHD63DAOC9JU0H11+*4.\$S6ZC0JBZAB-C3QHISKE MCAOI8%M3V96-PY\$N6XOWLIBPIAYU:*JIRHUF2XZQ4H9 XJ72WG1K36VF/9BL56%E8T1OEEG%5TW5A 6YO67N6UCE:WT6BT-UMM:ABJK2TMDN1:FW-%T+\$D78NDSC3%5F61NYS-P9LOE0%J/ZAY:N5L4H-H/LH:AO3FU JHG7K46IOIMT.RE%PHLA21JRI3HTC\$AH"
+    private val testCertificateData = VaccinationCertificateData(
+        header = mockk(),
+        certificate = VaccinationDGCV1(
+            version = "1",
+            nameData = VaccinationDGCV1.NameData(
+                familyName = "Kevin",
+                familyNameStandardized = "Kevin2",
+                givenName = "Bob",
+                givenNameStandardized = "Bob2"
+            ),
+            dob = "1969-11-16",
+            vaccinationDatas = listOf(
+                VaccinationDGCV1.VaccinationData(
+                    targetId = "12345",
+                    vaccineId = "1214765",
+                    medicalProductId = "aaEd/easd",
+                    marketAuthorizationHolderId = "ASD-2312",
+                    doseNumber = 2,
+                    totalSeriesOfDoses = 5,
+                    dt = "1969-04-20",
+                    countryOfVaccination = "DE",
+                    certificateIssuer = "Herbert",
+                    uniqueCertificateIdentifier = "urn:uvci:01:NL:PlA8UWS60Z4RZXVALl6GAZ"
+                )
+            )
+        )
+    )
+
+    @BeforeEach
+    fun setUp() {
+        MockKAnnotations.init(this)
+    }
+
+    @AfterEach
+    fun teardown() {
+        CertificateQrCodeCensor.clearCertificateToCensor()
+        CertificateQrCodeCensor.clearQRCodeStringToCensor()
+    }
+
+    private fun createInstance() = CertificateQrCodeCensor()
+
+    @Test
+    fun `checkLog() should return censored LogLine`() = runBlockingTest {
+        CertificateQrCodeCensor.addQRCodeStringToCensor(testRawString)
+        CertificateQrCodeCensor.addCertificateToCensor(testCertificateData)
+
+        val censor = createInstance()
+
+        val logLineToCensor = LogLine(
+            timestamp = 1,
+            priority = 3,
+            message = "Here comes the rawString: $testRawString of the vaccine certificate",
+            tag = "I am tag",
+            throwable = null
+        )
+
+        censor.checkLog(logLineToCensor) shouldBe logLineToCensor.copy(
+            message = "Here comes the rawString: ########-####-####-####-########C\$AH of the vaccine certificate",
+        )
+
+        val certDataToCensor = LogLine(
+            timestamp = 1,
+            priority = 3,
+            message = "Hello my name is Kevin Bob, i was born at 1969-11-16, i have been " +
+                "vaccinated with: 12345 1214765 aaEd/easd ASD-2312 1969-04-20 DE Herbert" +
+                " urn:uvci:01:NL:PlA8UWS60Z4RZXVALl6GAZ",
+            tag = "I am tag",
+            throwable = null
+        )
+
+        censor.checkLog(certDataToCensor) shouldBe certDataToCensor.copy(
+            message = "Hello my name is nameData/familyName nameData/givenName, i was born at " +
+                "vaccinationCertificate/dob, i have been vaccinated with: vaccinationData/targetId " +
+                "vaccinationData/vaccineId vaccinationData/medicalProductId" +
+                " vaccinationData/marketAuthorizationHolderId vaccinationData/dt" +
+                " vaccinationData/countryOfVaccination vaccinationData/certificateIssuer" +
+                " vaccinationData/uniqueCertificateIdentifier"
+        )
+    }
+
+    @Test
+    fun `checkLog() should return null if no data to censor was set`() = runBlockingTest {
+        val censor = createInstance()
+
+        val logLineNotToCensor = LogLine(
+            timestamp = 1,
+            priority = 3,
+            message = "Here comes the rawData: $testRawString",
+            tag = "I am tag",
+            throwable = null
+        )
+
+        censor.checkLog(logLineNotToCensor) shouldBe null
+    }
+
+    @Test
+    fun `checkLog() should return null if nothing should be censored`() = runBlockingTest {
+        CertificateQrCodeCensor.addQRCodeStringToCensor(testRawString.replace("1", "2"))
+        CertificateQrCodeCensor.addCertificateToCensor(testCertificateData)
+
+        val censor = createInstance()
+
+        val logLineNotToCensor = LogLine(
+            timestamp = 1,
+            priority = 3,
+            message = "Here comes the rawString: $testRawString",
+            tag = "I am tag",
+            throwable = null
+        )
+
+        censor.checkLog(logLineNotToCensor) shouldBe null
+    }
+}